Commit 36bfcce
[analytics-engine] Coverage fixes for search command on the analytics-engine route (opensearch-project#21681)
* [analytics-backend-datafusion] Register TIMESTAMP in STANDARD_PROJECT_OPS
PPL `timestamp(expr)` lowers to a `ScalarFunction.TIMESTAMP` call. The
TimestampFunctionAdapter already wires the call into DataFusion's native
`to_timestamp`, but `STANDARD_PROJECT_OPS` did not declare TIMESTAMP, so
`OpenSearchProjectRule.annotateExpr` rejected every plan that contained
the operator with "No backend supports scalar function [TIMESTAMP]
among [datafusion]".
Same call also shows up implicitly after the analyzer coerces a string
literal to TIMESTAMP for column comparisons such as
`@timestamp="2024-01-15T10:30:00Z"` once `@timestamp` is typed as
TIMESTAMP (see the date_nanos schema fix in the previous commit).
Update the inline comment block to match: the legacy-engine-only path
the prior comment described is gone now that the capability is wired.
Signed-off-by: Kai Huang <ahkcs@amazon.com>
* [analytics-engine] Catch Calcite Litmus.THROW AssertionError in DefaultPlanExecutor
RexUtil.isFlat / RelOptUtil.eq / Project.isValid / RexChecker call into
Calcite's Litmus.THROW, which raises AssertionError from raw Java code
rather than via the `assert` keyword. JVM `-da` doesn't gate that path,
so an assertion firing inside a search thread escapes to
OpenSearchUncaughtExceptionHandler and exits the cluster JVM.
This bit hard once `CalciteRelNodeVisitor` started lowering structured
PPL `search` predicates to native filter shape: queries like
`severityNumber="not-a-number"` fold to `=(SAFE_CAST($X), null)` ahead of
the marking phase, and the Litmus check fires before any plan-executor
listener gets to translate the error. The cluster died mid-IT and 21
subsequent tests failed with `Connection refused`.
Convert AssertionError caught at the executor entrypoint to an
IllegalStateException so the query reports as HTTP 500 with a
bucketable message and the cluster survives. The same pattern is
already in place at `UnifiedQueryPlanner.plan` on the SQL plugin side;
this is the analytics-engine-side mirror so neither layer can produce a
cluster-fatal assertion.
Signed-off-by: Kai Huang <ahkcs@amazon.com>
* [analytics-backend-datafusion] Preserve fractional seconds in DatetimeOutputCastRewriter format
Widen the format string passed to `to_char` from the seconds-only
{@code "%Y-%m-%d %H:%M:%S"} to {@code "%Y-%m-%d %H:%M:%S%.f"}. The
trailing {@code %.f} is chrono's variable-length fractional-second
specifier — a leading dot followed by 0-9 digits, omitted when the
value has no sub-second precision.
This matches PPL's legacy formatting for {@code date} and
{@code date_nanos} fields where the displayed precision tracks the
source value:
- {@code 2024-01-15T10:30:01.23456789Z} (date_nanos) →
{@code "2024-01-15 10:30:01.23456789"} (legacy) / now
{@code "2024-01-15 10:30:01.234567890"} (analytics route — internally
9-digit, leading 0 because Arrow Timestamp(ns) precision is fixed)
- {@code 2025-08-01T03:47:41Z} (date) →
{@code "2025-08-01 03:47:41"} (both paths) — no decimal because the
source value has no fractional component
Surfaced by `CalciteSearchCommandIT.testSearchWithDateRangeComparisons`.
Follow-up to opensearch-project/sql#5420 which the original PR (opensearch-project#21650)
closed with a seconds-only format that dropped the fractional digits
the tests still expect.
Signed-off-by: Kai Huang <ahkcs@amazon.com>
* [analytics-backend-datafusion] Apply schema coercion on indexed-executor placeholder
The indexed-execution path inferred the parquet schema via build_segments
(which calls FileFormat::infer_schema) and registered it directly on the
PlaceholderProvider that from_substrait_plan binds against. The non-indexed
paths (session_context.rs, query_executor.rs, api.rs) all routed their
inferred schemas through schema_coerce::coerce_inferred_schema before
registering, but the indexed path skipped this step.
Result: an OpenSearch `ip` column lands as parquet `BinaryView` on disk;
isthmus on the Java side serializes the Substrait base schema as plain
`Binary` (Substrait has no view types). The placeholder reports `BinaryView`
while the plan declares `Binary` — DataFusion's substrait consumer rejects
the bind with:
Substrait error: Field '<x>' in Substrait schema has a different type
(Binary) than the corresponding field in the table schema (BinaryView).
Every analytics-engine query against an index that includes an `ip` column
(every OTEL-logs query in CalciteSearchCommandIT, for example) fails at
fragment start.
Apply coerce_inferred_schema right after build_segments, before
PlaceholderProvider construction. The placeholder, the
expr_to_bool_tree analysis, and the downstream IndexedTableProvider all
see the same Substrait-compatible (Binary / Int64 / Float32) schema, so
the bind succeeds and the parquet reader's SchemaAdapter handles the
per-batch BinaryView→Binary relabeling at scan time.
This restores parity with the other infer_schema sites; no behavior
change for non-IP columns.
Signed-off-by: Kai Huang <ahkcs@amazon.com>
---------
Signed-off-by: Kai Huang <ahkcs@amazon.com>1 parent f669b8e commit 36bfcce
5 files changed
Lines changed: 30 additions & 14 deletions
File tree
- sandbox/plugins
- analytics-backend-datafusion
- rust/src
- src
- main/java/org/opensearch/be/datafusion
- test/java/org/opensearch/be/datafusion
- analytics-engine/src/main/java/org/opensearch/analytics/exec
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
450 | 450 | | |
451 | 451 | | |
452 | 452 | | |
| 453 | + | |
453 | 454 | | |
454 | 455 | | |
455 | 456 | | |
| |||
Lines changed: 2 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
232 | 232 | | |
233 | 233 | | |
234 | 234 | | |
| 235 | + | |
235 | 236 | | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
| 237 | + | |
240 | 238 | | |
241 | 239 | | |
242 | 240 | | |
| |||
Lines changed: 8 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
86 | 92 | | |
87 | | - | |
| 93 | + | |
88 | 94 | | |
89 | 95 | | |
90 | 96 | | |
| |||
Lines changed: 11 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
58 | | - | |
59 | | - | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
60 | 63 | | |
61 | 64 | | |
62 | 65 | | |
| |||
236 | 239 | | |
237 | 240 | | |
238 | 241 | | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
244 | 247 | | |
245 | 248 | | |
246 | 249 | | |
| |||
255 | 258 | | |
256 | 259 | | |
257 | 260 | | |
258 | | - | |
| 261 | + | |
259 | 262 | | |
260 | 263 | | |
261 | 264 | | |
| |||
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
121 | 129 | | |
122 | 130 | | |
123 | 131 | | |
| |||
0 commit comments