// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// `Array` 列的取数。上游 `parseArrayData` 走的是 `ArrayArray`:
// 外层 `data` 是每行一个 `ScalarField`,元素类型在 `element_type`。
// 数组元素只能是标量,所以这里只需要认识标量那几条。
///|
/// `Array` 列的每一行。
fn array_rows(
field : @schema.FieldData,
begin : Int,
end : Int,
valid : Array[Bool],
) -> Array[ArrayValue] raise ColumnError {
let s = scalar_payload(field, "array_data")
match s.data {
@schema.ScalarField_Data::ArrayData(a) => {
let logical = logical_len(a.data.length(), valid)
check_range(field.field_name, begin, end, logical)
let e = normalize_end(end, logical)
let b = clamp_begin(begin, logical)
let rows : Array[ArrayValue] = []
for i = b; i < e; i = i + 1 {
rows.push(array_cell(field.field_name, a.element_type, a.data[i]))
}
rows
}
_ => raise missing_scalar(field, "not array_data")
}
}
///|
/// 一行数组值。`ArrayArray.element_type` 说这行的元素是什么标量类型,
/// 不认识就报错,不落到「当字符串读」这种猜测上。
fn array_cell(
field_name : String,
element_type : @schema.DataType,
row : @schema.ScalarField,
) -> ArrayValue raise ColumnError {
match element_type {
@schema.DataType::Bool =>
match row.data {
@schema.ScalarField_Data::BoolData(a) => ArrayValue::Bool(a.data)
_ => raise array_element_mismatch(field_name, "bool")
}
@schema.DataType::Int8 =>
match row.data {
@schema.ScalarField_Data::IntData(a) =>
ArrayValue::Int8(a.data.map(narrow_int8))
_ => raise array_element_mismatch(field_name, "int8")
}
@schema.DataType::Int16 =>
match row.data {
@schema.ScalarField_Data::IntData(a) =>
ArrayValue::Int16(a.data.map(narrow_int16))
_ => raise array_element_mismatch(field_name, "int16")
}
@schema.DataType::Int32 =>
match row.data {
@schema.ScalarField_Data::IntData(a) => ArrayValue::Int32(a.data)
_ => raise array_element_mismatch(field_name, "int32")
}
@schema.DataType::Int64 =>
match row.data {
@schema.ScalarField_Data::LongData(a) => ArrayValue::Int64(a.data)
_ => raise array_element_mismatch(field_name, "int64")
}
@schema.DataType::Float =>
match row.data {
@schema.ScalarField_Data::FloatData(a) => ArrayValue::Float(a.data)
_ => raise array_element_mismatch(field_name, "float")
}
@schema.DataType::Double =>
match row.data {
@schema.ScalarField_Data::DoubleData(a) => ArrayValue::Double(a.data)
_ => raise array_element_mismatch(field_name, "double")
}
@schema.DataType::String
| @schema.DataType::VarChar
| @schema.DataType::Text =>
match row.data {
@schema.ScalarField_Data::StringData(a) => ArrayValue::String(a.data)
_ => raise array_element_mismatch(field_name, "string")
}
other =>
raise UnsupportedType(
"array field \{field_name} has unsupported element type \{data_type_name(other)}",
)
}
}
///|
fn array_element_mismatch(field_name : String, want : String) -> ColumnError {
MalformedPayload(
"array field \{field_name} declares element type \{want} but the row carries other data",
)
}