/** * @param {SchemaElement[]} schema * @param {KeyValue[] | undefined} key_value_metadata * @returns {void} */ export function markGeoColumns(schema, key_value_metadata) { // Prepare the list of GeoParquet columns /** @type {Map} */ const columns = new Map() const geo = key_value_metadata?.find(({ key }) => key === 'geo')?.value const decodedColumns = (geo && JSON.parse(geo)?.columns) ?? {} for (const [name, column] of Object.entries(decodedColumns)) { if (column.encoding !== 'WKB') continue const type = column.edges === 'spherical' ? 'GEOGRAPHY' : 'GEOMETRY' const id = column.crs?.id ?? column.crs?.ids?.[0] const crs = id ? `${id.authority}:${id.code.toString()}` : undefined // Note: we can't infer GEOGRAPHY's algorithm from GeoParquet columns.set(name, { type, crs }) } // Mark schema elements with logical type // Only look at root-level columns of type BYTE_ARRAY without existing logical_type for (let i = 1; i < schema.length; i++) { // skip root const { logical_type, name, num_children, type } = schema[i] if (num_children) { i += num_children continue // skip the element and its children } if (type === 'BYTE_ARRAY' && !logical_type) { schema[i].logical_type = columns.get(name) } } } /** * @import {KeyValue, LogicalType, SchemaElement} from '../src/types.js' */