blob: 6e1d83cb9109ba5f700e3622597415a453d37f4b [file]
################################################################################
# Licensed to the Apache Software Foundation (ASF) 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.
################################################################################
"""Extract field references for shared query-authorization validation."""
import json
# REST DateExtractTransform names are metadata, independent of Arrow execution.
_DATE_EXTRACT_NAMES = frozenset((
'YEAR',
'MONTH',
'DAY',
'HOUR',
'MINUTE',
'SECOND',
'QUARTER',
'DAY_OF_YEAR',
'WEEKDAY',
'ISO_DAY_OF_WEEK',
'DAY_OF_WEEK',
'WEEK',
'YEAR_OF_WEEK',
))
def extract_referenced_fields(json_str: str) -> set:
data = json.loads(json_str)
fields = set()
_collect_fields(data, fields)
return fields
def _collect_fields(data: dict, fields: set):
kind = data.get("kind")
if kind == "LEAF":
_collect_all_field_refs_from_transform(data["transform"], fields)
elif kind == "COMPOUND":
for child in data["children"]:
_collect_fields(child, fields)
def _collect_all_field_refs_from_transform(transform: dict, fields: set = None) -> set:
if fields is None:
fields = set()
name = transform.get("name")
if (name in ("FIELD_REF", "CAST") or name in _DATE_EXTRACT_NAMES) and "fieldRef" in transform:
fields.add(transform["fieldRef"]["name"])
else:
for inp in transform.get("inputs", []):
if isinstance(inp, dict) and "name" in inp:
# _resolve_transform_input reads every dict input as a column by name
fields.add(inp["name"])
_collect_all_field_refs_from_transform(inp, fields)
return fields