Skip to content

HIVE-29628: Incorrect objectName in PARTITION HivePrivilegeObject for…#6508

Open
rtrivedi12 wants to merge 1 commit into
apache:masterfrom
rtrivedi12:HIVE-29628
Open

HIVE-29628: Incorrect objectName in PARTITION HivePrivilegeObject for…#6508
rtrivedi12 wants to merge 1 commit into
apache:masterfrom
rtrivedi12:HIVE-29628

Conversation

@rtrivedi12
Copy link
Copy Markdown
Contributor

… view queries on partitioned tables

What changes were proposed in this pull request?

Fixed incorrect PARTITION HivePrivilegeObject generation in CommandAuthorizerV2 for queries that access a regular (non-deferred) view over a partitioned base table.
In CommandAuthorizerV2.getHivePrivObjects(), skip emitting a HivePrivilegeObject for PARTITION / DUMMYPARTITION entities when access is through a regular view. The view’s TABLE_OR_VIEW object already covers authorization.

Skip logic (isPartitionAccessedViaRegularView):

  1. If the partition entity has a regular (non-deferred) view parent → skip.
  2. If the partition entity lacks parent entity but a sibling indirect TABLE entity for the same base table has a regular view parent → skip.
  3. If the partition is accessed through a deferred-auth view (Authorized=false) → emit PARTITION on the base table (existing behaviour).
  4. If the partition is accessed directly (no view) → emit PARTITION on the base table

Why are the changes needed?

HIVE-27892 added handling for PARTITION / DUMMYPARTITION entities in addHivePrivObject, always using the physical base-table name (datadb/t1). For view queries, this causes authorizers to receive an extra PARTITION object on the base table in addition to the view’s TABLE_OR_VIEW object. Users with view-only policies are getting PERMISSION denied.

Does this PR introduce any user-facing change?

yes
View queries through regular views send only the view TABLE_OR_VIEW privilege object. Direct queries on partitioned tables and deferred-auth views still emit base-table PARTITION objects as before.

How was this patch tested?

mvn test -Dtest=TestViewPartitionPrivilegeObjects

Comment on lines +206 to +225
for (Entity entity : allEntities) {
if (!(entity instanceof ReadEntity) || entity.getTyp() != Type.TABLE) {
continue;
}
ReadEntity tableEntity = (ReadEntity) entity;
if (tableEntity.isDirect() || tableEntity.getTable() == null) {
continue;
}
Table table = tableEntity.getTable();
if (!partTable.getDbName().equals(table.getDbName())
|| !partTable.getTableName().equals(table.getTableName())) {
continue;
}
if (hasDeferredViewParent(tableEntity)) {
return false;
}
if (hasRegularViewParent(tableEntity)) {
return true;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't quite understand this logic. Why do we need to check all the entites for a given partition object. This potentially lead to O(N^2) for huge partitioned table creating a bottleneck during compile phase (because authorization happens here)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this whole method needs a refactor to simplify it as there are too many continues and ifs.

Comment on lines +234 to +239
for (ReadEntity parent : parents) {
if (parent.getTyp() == Type.TABLE && parent.getTable() != null
&& isDeferredAuthView(parent.getTable())) {
return true;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can also lead to O(N^2). same with hasRegularViewParent() also.

@sonarqubecloud
Copy link
Copy Markdown


if ((privObject.getTyp() == Type.PARTITION || privObject.getTyp() == Type.DUMMYPARTITION)
&& privObject instanceof ReadEntity
&& isPartitionAccessedViaRegularView((ReadEntity) privObject, privObjects)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method is specific enough that the if condition can be completely checked in the method and we can just simplify this to

if (isPartitionAccessedViaRegularView(privObject, privObjects))

so that it's easier to read. What do you think?

Comment on lines +206 to +225
for (Entity entity : allEntities) {
if (!(entity instanceof ReadEntity) || entity.getTyp() != Type.TABLE) {
continue;
}
ReadEntity tableEntity = (ReadEntity) entity;
if (tableEntity.isDirect() || tableEntity.getTable() == null) {
continue;
}
Table table = tableEntity.getTable();
if (!partTable.getDbName().equals(table.getDbName())
|| !partTable.getTableName().equals(table.getTableName())) {
continue;
}
if (hasDeferredViewParent(tableEntity)) {
return false;
}
if (hasRegularViewParent(tableEntity)) {
return true;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this whole method needs a refactor to simplify it as there are too many continues and ifs.

&& BASE_TABLE.equalsIgnoreCase(h.getObjectName())
&& DATA_DB.equalsIgnoreCase(h.getDbname())));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need tests for the sibling logic (Skip logic #2 from the PR description).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants