Class DatasetRewriter
FROM <dataset> into the same UnresolvedExternalRelation the
EXTERNAL command produces, so both paths converge at the existing resolver + analyzer.
Runs once on the parsed plan before pre-analysis.
Pattern expansion (wildcards, exclusions, date math, hidden flag) is not done here. It happens in the
authorization engine: DatasetResolver dispatches each relation's raw FROM patterns to
EsqlResolveDatasetAction, whose body calls resolve(java.lang.String[], java.lang.String[], org.elasticsearch.cluster.metadata.ProjectMetadata, org.elasticsearch.cluster.metadata.IndexNameExpressionResolver) to expand
the patterns against the caller's authorized abstractions (wildcard expansion lands where authorization lives, not
client-side). resolve(java.lang.String[], java.lang.String[], org.elasticsearch.cluster.metadata.ProjectMetadata, org.elasticsearch.cluster.metadata.IndexNameExpressionResolver) returns, per relation, the authorized concrete dataset names plus whether the
relation also targets non-dataset abstractions. rewrite(org.elasticsearch.xpack.esql.plan.logical.LogicalPlan, org.elasticsearch.cluster.metadata.ProjectMetadata, java.util.Map<org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution>, boolean)/rewriteOne(org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.cluster.metadata.DatasetMetadata, org.elasticsearch.xpack.esql.datasources.metadata.DataSourceMetadata, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution, boolean) then consume that
DatasetRewriter.DatasetResolution to build the plan — they no longer resolve, expand, or gate on authorization.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordPer-relation result ofresolve(java.lang.String[], java.lang.String[], org.elasticsearch.cluster.metadata.ProjectMetadata, org.elasticsearch.cluster.metadata.IndexNameExpressionResolver): the authorized concrete dataset names the relation targets, the concrete non-dataset names resolved from the same pattern (drives heterogeneous-FROMUnionAllbuilding), and the explicitly-named datasets absent from the authorized set (surfaced byrewriteOne(org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.cluster.metadata.DatasetMetadata, org.elasticsearch.xpack.esql.datasources.metadata.DataSourceMetadata, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution, boolean)asUnknown index). -
Field Summary
Fields -
Method Summary
Modifier and TypeMethodDescriptionresolve(String[] authorizedIndices, String[] rawPatterns, ProjectMetadata projectMetadata, IndexNameExpressionResolver iner) Per-relation engine-side resolution, run from theEsqlResolveDatasetActionbody.static LogicalPlanrewrite(LogicalPlan parsed, ProjectMetadata projectMetadata, Map<UnresolvedRelation, DatasetRewriter.DatasetResolution> resolutions, boolean crossProjectEnabled) Walksparsedand rewrites everyUnresolvedRelationthat resolved to authorized dataset(s) intoUnresolvedExternalRelation(single dataset) orUnionAllof such (multi), using the per-relationDatasetRewriter.DatasetResolutioncomputed engine-side byresolve(java.lang.String[], java.lang.String[], org.elasticsearch.cluster.metadata.ProjectMetadata, org.elasticsearch.cluster.metadata.IndexNameExpressionResolver).static LogicalPlanrewriteUnsecured(LogicalPlan parsed, ProjectMetadata projectMetadata, IndexNameExpressionResolver iner) Convenience entry for an unsecured context (security disabled, or tests): resolves every dataset-candidate relation with the full authorized set andrewrite(org.elasticsearch.xpack.esql.plan.logical.LogicalPlan, org.elasticsearch.cluster.metadata.ProjectMetadata, java.util.Map<org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution>, boolean)s — the in-process equivalent ofDatasetResolver's dispatch, minus theEsqlResolveDatasetActionround-trip.
-
Field Details
-
RESOLVER_OPTIONS
IndexResolver.DEFAULT_OPTIONS(which carriesALLOW_UNAVAILABLE_TARGETS) plusresolveDatasets(true). Shared withEsqlResolveDatasetAction.Request, so the security filter silently narrows an unauthorized concrete dataset name to nothing rather than throwing a403— a403on an explicit name would be an existence oracle ("this dataset exists but you can't read it"). Existence-hiding is completed inrewriteOne(org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.cluster.metadata.DatasetMetadata, org.elasticsearch.xpack.esql.datasources.metadata.DataSourceMetadata, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution, boolean), which surfaces an explicitly-named-but-unauthorized dataset as the sameUnknown index(400) a missing index gives — seeresolve(java.lang.String[], java.lang.String[], org.elasticsearch.cluster.metadata.ProjectMetadata, org.elasticsearch.cluster.metadata.IndexNameExpressionResolver).
-
-
Method Details
-
resolve
public static DatasetRewriter.DatasetResolution resolve(String[] authorizedIndices, String[] rawPatterns, ProjectMetadata projectMetadata, IndexNameExpressionResolver iner) Per-relation engine-side resolution, run from theEsqlResolveDatasetActionbody. Returns the authorized dataset names, the concrete non-dataset names resolved from the same pattern (used in heterogeneous-FROMUnionAllbuilding), and the explicitly-named-but-unauthorized datasets — whichrewriteOne(org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.cluster.metadata.DatasetMetadata, org.elasticsearch.xpack.esql.datasources.metadata.DataSourceMetadata, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution, boolean)surfaces asUnknown index(400), the same error a missing index gives, so an unauthorized dataset can't be told apart from a missing name. -
rewriteUnsecured
public static LogicalPlan rewriteUnsecured(LogicalPlan parsed, ProjectMetadata projectMetadata, IndexNameExpressionResolver iner) Convenience entry for an unsecured context (security disabled, or tests): resolves every dataset-candidate relation with the full authorized set andrewrite(org.elasticsearch.xpack.esql.plan.logical.LogicalPlan, org.elasticsearch.cluster.metadata.ProjectMetadata, java.util.Map<org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution>, boolean)s — the in-process equivalent ofDatasetResolver's dispatch, minus theEsqlResolveDatasetActionround-trip.nullor dataset-free project is a no-op. -
rewrite
public static LogicalPlan rewrite(LogicalPlan parsed, ProjectMetadata projectMetadata, Map<UnresolvedRelation, DatasetRewriter.DatasetResolution> resolutions, boolean crossProjectEnabled) Walksparsedand rewrites everyUnresolvedRelationthat resolved to authorized dataset(s) intoUnresolvedExternalRelation(single dataset) orUnionAllof such (multi), using the per-relationDatasetRewriter.DatasetResolutioncomputed engine-side byresolve(java.lang.String[], java.lang.String[], org.elasticsearch.cluster.metadata.ProjectMetadata, org.elasticsearch.cluster.metadata.IndexNameExpressionResolver). All other relations are left untouched. TheprojectMetadata == null/ no-datasets-registered short-circuits avoid touching the common path.Throws
VerificationExceptionfor: non-STANDARDIndexModeon a dataset, orUnionAllbranch-cap exceeded. Designed to run once on the parsed plan before pre-analysis (so the analyzer sees a uniformUnresolvedExternalRelationtree regardless of whether the user wroteFROM <dataset>or inlineEXTERNAL).- Parameters:
resolutions- per-relation resolution keyed by relation identity (seeDatasetResolver). A relation absent from the map (e.g. remote-prefixed, or no pattern could match a dataset name) is left unchanged.crossProjectEnabled- whether cross-project search (CPS) is active; whentrue, a wildcard that matched a dataset is kept alongside the dataset so the remote (linked-project) half still resolves — seerewriteOne(org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation, org.elasticsearch.cluster.metadata.DatasetMetadata, org.elasticsearch.xpack.esql.datasources.metadata.DataSourceMetadata, org.elasticsearch.xpack.esql.datasources.DatasetRewriter.DatasetResolution, boolean).
-