Fang-Yu Rao created CALCITE-7152:
------------------------------------
Summary: Make validateIdentifier() in SqlValidatorImpl.java also
return the fully qualified identifier
Key: CALCITE-7152
URL: https://issues.apache.org/jira/browse/CALCITE-7152
Project: Calcite
Issue Type: Wish
Reporter: Fang-Yu Rao
In some scenarios, it may be helpful if {{validateIdentifier()}} in
[SqlValidatorImpl.java|https://github.com/apache/calcite/blob/main/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java]
could also return the fully qualified identifier once the given
{{SqlIdentifier}} could be successfully resolved.
For instance, when validating a given query, Apache Impala would need to
register the privilege request for a column once the corresponding
{{SqlIdentifier}} could be successfully resolved. In such a case, the fully
qualified (resolved) identifier of the column would be needed to register the
privilege request for the column, which will be checked by Impala's
authorization checker later on to make sure the requesting user is granted the
required permission on the selected column.
The following is a code snippet from
[https://gerrit.cloudera.org/c/22716/20/java/calcite-planner/src/main/java/org/apache/impala/calcite/service/ImpalaSqlValidatorImpl.java]
that demonstrates how Apache Impala could register such a privilege request
for a column. It could be seen that to get the fully qualified identifier, we
need to call {{scope.fullyQualify(id)}} in the overridden method again. Thus,
it would be nice if {{validateIdentifier()}} in the parent class already
returns the fully qualified identifier.
{code:java}
@Override public void validateIdentifier(SqlIdentifier id, SqlValidatorScope
scope) {
super.validateIdentifier(id, scope);
// It is a bit inefficient to execute scope.fullyQualify() again because
this has
// been done within super.validateIdentifier(id, scope). But since we need
'fqId'
// to register the privilege request, we have to do this for now.
SqlQualified fqId = scope.fullyQualify(id);
SqlIdentifier prefix = id.getComponent(0, 1);
SqlNameMatcher nameMatcher = this.getCatalogReader().nameMatcher();
ResolvedImpl resolved = new ResolvedImpl();
SqlValidatorNamespace fromNs;
scope.resolve(prefix.names, nameMatcher, false, resolved);
if (resolved.count() == 1) {
Resolve resolve = resolved.only();
fromNs = resolve.namespace;
SqlValidatorTable validatorTable = fromNs.getTable();
if (validatorTable instanceof CalciteTable) {
FeFsTable feFsTable = ((CalciteTable) validatorTable).getFeFsTable();
this.analyzer_.registerPrivReq(
builder -> builder.allOf(Privilege.SELECT)
.onColumn(feFsTable.getDb().getName(),
feFsTable.getTableName().getTbl(),
fqId.identifier.names.get(1),
feFsTable.getOwnerUser()).build()
);
return;
}
// A view would be an instance of RelOptTableImpl if the view was created
via
// CalciteDb.Builder#createViewTable().
if (validatorTable instanceof RelOptTableImpl) {
Preconditions.checkState(validatorTable.table() instanceof
ImpalaViewTable);
FeView view = ((ImpalaViewTable) validatorTable.table()).getFeView();
this.analyzer_.registerPrivReq(
builder -> builder.allOf(Privilege.SELECT)
.onColumn(view.getDb().getName(),
view.getTableName().getTbl(), fqId.identifier.names.get(1),
view.getOwnerUser()).build()
);
}
}
}
{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)