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)

Reply via email to