[ 
https://issues.apache.org/jira/browse/HIVE-30196?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Yuming Wang updated HIVE-30196:
-------------------------------
    Description: 
h3. Problem

{\{get_partitions_with_specs}} (thrift RPC introduced by HIVE-20306) skipped 
the \{{hive.metastore.limit.partition.request}} guard that every regular 
partition listing RPC enforces (\{{get_partitions}}, 
\{{get_partitions_by_names}}, \{{get_partitions_with_auth}}, 
\{{get_partitions_by_filter}}, \{{get_partitions_by_expr}}, 
\{{get_partitions_ps}}, \{{get_partitions_ps_with_auth}}). The request has no 
client-side max parameter, so one call made the metastore materialize all 
matching partitions server-side.

h3. Fix

* Fail fast *before* the partition fetch, using the same cheap count queries 
the regular listing RPCs use, mapped per filter mode:
** filter spec unset -> \{{rs.getNumPartitionsByFilter(cat, db, tbl, "")}}
** BY_NAMES -> the requested partition names count (as 
\{{get_partitions_by_names}} does)
** BY_VALUES -> \{{rs.getNumPartitionsByPs}} (same 
\{{MetaStoreUtils.makePartNameMatcher}} predicate as the fetch, both SQL and 
JDO paths)
** BY_EXPR -> \{{rs.getNumPartitionsByFilter}} on the joined expressions (same 
\{{PartFilterExprUtil}} grammar the projection path parses)
* Keep a check on the fetched result size as the final backstop (covers the 
count/fetch TOCTOU window and unknown filter modes)
* Add \{{get_partitions_with_specs}} to the \{{LIMIT_PARTITION_REQUEST}} config 
description

Authorization ordering is preserved: \{{firePreEvent}} (pre-event listeners) 
still runs before the limit checks.

h3. Behavior changes (only when the operator configures the limit; default -1 
is unchanged)

* Requests matching more partitions than the limit now throw \{{MetaException}} 
(same message/config as the regular RPCs)
* BY_NAMES uses the strict requested-count semantics, mirroring 
\{{get_partitions_by_names}} (requesting more names than the limit fails even 
if fewer exist)
* no-filter / BY_VALUES / BY_EXPR requests pay one extra count query per 
request; BY_NAMES is free

h3. Tests

Added to \{{TestGetPartitionsUsingProjectionAndFilterSpecs}} (limit=100, table 
with 101 partitions): exceed (no filter), at-limit boundary (exactly 100 
succeeds), BY_NAMES exceed, BY_NAMES requested-count exceed (150 requested / 50 
existing — pins the strict semantics), BY_VALUES exceed, BY_EXPR exceed, and a 
JDO-path variant (DirectSQL disabled). All 32 tests plus the related suites 
(\{{TestRemoteHiveMetaStore}}, \{{TestEmbeddedHiveMetaStore}}, 
\{{TestHmsServerAuthorization}}) pass.

h3. Follow-ups

* Push the limit down into 
\{{MetaStoreDirectSql.getPartitionIdsViaSqlFilter(max)}} (the projection path 
currently passes \{{null}}) to bound the ID query with limit+1 in one round 
trip and remove the extra count query + TOCTOU window.
* Related: HIVE-30195 — the same RPC also skips the table-level filter hook 
check (\{{checkDbAndTableFilters}}); same class of gap.

> get_partitions_with_specs skips hive.metastore.limit.partition.request 
> enforcement performed by all regular partition listing RPCs
> ----------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HIVE-30196
>                 URL: https://issues.apache.org/jira/browse/HIVE-30196
>             Project: Hive
>          Issue Type: Sub-task
>            Reporter: Yuming Wang
>            Priority: Major
>
> h3. Problem
> {\{get_partitions_with_specs}} (thrift RPC introduced by HIVE-20306) skipped 
> the \{{hive.metastore.limit.partition.request}} guard that every regular 
> partition listing RPC enforces (\{{get_partitions}}, 
> \{{get_partitions_by_names}}, \{{get_partitions_with_auth}}, 
> \{{get_partitions_by_filter}}, \{{get_partitions_by_expr}}, 
> \{{get_partitions_ps}}, \{{get_partitions_ps_with_auth}}). The request has no 
> client-side max parameter, so one call made the metastore materialize all 
> matching partitions server-side.
> h3. Fix
> * Fail fast *before* the partition fetch, using the same cheap count queries 
> the regular listing RPCs use, mapped per filter mode:
> ** filter spec unset -> \{{rs.getNumPartitionsByFilter(cat, db, tbl, "")}}
> ** BY_NAMES -> the requested partition names count (as 
> \{{get_partitions_by_names}} does)
> ** BY_VALUES -> \{{rs.getNumPartitionsByPs}} (same 
> \{{MetaStoreUtils.makePartNameMatcher}} predicate as the fetch, both SQL and 
> JDO paths)
> ** BY_EXPR -> \{{rs.getNumPartitionsByFilter}} on the joined expressions 
> (same \{{PartFilterExprUtil}} grammar the projection path parses)
> * Keep a check on the fetched result size as the final backstop (covers the 
> count/fetch TOCTOU window and unknown filter modes)
> * Add \{{get_partitions_with_specs}} to the \{{LIMIT_PARTITION_REQUEST}} 
> config description
> Authorization ordering is preserved: \{{firePreEvent}} (pre-event listeners) 
> still runs before the limit checks.
> h3. Behavior changes (only when the operator configures the limit; default -1 
> is unchanged)
> * Requests matching more partitions than the limit now throw 
> \{{MetaException}} (same message/config as the regular RPCs)
> * BY_NAMES uses the strict requested-count semantics, mirroring 
> \{{get_partitions_by_names}} (requesting more names than the limit fails even 
> if fewer exist)
> * no-filter / BY_VALUES / BY_EXPR requests pay one extra count query per 
> request; BY_NAMES is free
> h3. Tests
> Added to \{{TestGetPartitionsUsingProjectionAndFilterSpecs}} (limit=100, 
> table with 101 partitions): exceed (no filter), at-limit boundary (exactly 
> 100 succeeds), BY_NAMES exceed, BY_NAMES requested-count exceed (150 
> requested / 50 existing — pins the strict semantics), BY_VALUES exceed, 
> BY_EXPR exceed, and a JDO-path variant (DirectSQL disabled). All 32 tests 
> plus the related suites (\{{TestRemoteHiveMetaStore}}, 
> \{{TestEmbeddedHiveMetaStore}}, \{{TestHmsServerAuthorization}}) pass.
> h3. Follow-ups
> * Push the limit down into 
> \{{MetaStoreDirectSql.getPartitionIdsViaSqlFilter(max)}} (the projection path 
> currently passes \{{null}}) to bound the ID query with limit+1 in one round 
> trip and remove the extra count query + TOCTOU window.
> * Related: HIVE-30195 — the same RPC also skips the table-level filter hook 
> check (\{{checkDbAndTableFilters}}); same class of gap.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to