risingwave_frontend/handler/create_source/external_schema/iceberg.rs
1// Copyright 2024 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use anyhow::Context;
16
17use super::*;
18
19/// TODO: make hidden columns additional columns, instead of normal columns?
20pub async fn extract_iceberg_columns(
21 with_properties: &WithOptionsSecResolved,
22) -> anyhow::Result<Vec<ColumnCatalog>> {
23 let props = ConnectorProperties::extract(with_properties.clone(), true)?;
24 if let ConnectorProperties::Iceberg(properties) = props {
25 let table = properties.load_table().await?;
26 let iceberg_schema: arrow_schema_iceberg::Schema =
27 ::iceberg::arrow::schema_to_arrow_schema(table.metadata().current_schema())?;
28
29 let mut columns: Vec<ColumnCatalog> = iceberg_schema
30 .fields()
31 .iter()
32 .enumerate()
33 .map(|(i, field)| -> anyhow::Result<ColumnCatalog> {
34 let column_desc = ColumnDesc::named(
35 field.name(),
36 ColumnId::new((i + 1).try_into().unwrap()),
37 IcebergArrowConvert
38 .type_from_field(field)
39 .with_context(|| {
40 format!(
41 "failed to infer RisingWave type for Iceberg field {}",
42 field.name()
43 )
44 })?,
45 );
46 Ok(ColumnCatalog {
47 column_desc,
48 // hide the _row_id column for iceberg engine table
49 // This column is auto generated when users define a table without primary key
50 is_hidden: field.name() == ROW_ID_COLUMN_NAME,
51 })
52 })
53 .collect::<anyhow::Result<Vec<_>>>()?;
54 columns.extend(ColumnCatalog::iceberg_hidden_cols());
55
56 tracing::info!("iceberg columns: {:?}", columns);
57
58 Ok(columns)
59 } else {
60 Err(anyhow!(format!(
61 "Invalid properties for iceberg source: {:?}",
62 props
63 )))
64 }
65}