Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[BUG] spath and seven json functions return 500 or a wrong 200 on a field type they do not support

Aperta
#5,899 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
50/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
java
Ambito
backend, databases

Direzione di ricerca

Start with SPath.java and the JSON function implementations in core/src/main/java/org/opensearch/sql/expression/function/jsonUDF, especially JsonExtractFunctionImpl.java, then compare their operand metadata and return types with json_extract_all and json_array_length. Use the listed PPL queries and field mappings to check that unsupported operand types produce HTTP 400 errors with type details and that valid string inputs still work. Also verify json returns a string result for numeric and boolean inputs.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug PPL

Query Information

PPL Command/Query:

source=spx | spath input=n a

n is a long field.

Expected Result: HTTP 400 naming the expected and actual type. spath input=n on the same field, with no path, already returns a 400 that names the type, JSON_EXTRACT_ALL function expects {[STRING]}, but got [LONG].

Actual Result: HTTP 500.

{
  "error": {
    "context": {
      "stage": "executing",
      "stage_description": "Running the query"
    },
    "reason": "class java.lang.Long cannot be cast to class java.lang.String (java.lang.Long and java.lang.String are in module java.base of loader 'bootstrap')",
    "details": "class java.lang.Long cannot be cast to class java.lang.String (java.lang.Long and java.lang.String are in module java.base of loader 'bootstrap')",
    "location": ["while running the query"],
    "code": "UNKNOWN",
    "type": "ClassCastException"
  },
  "status": 500
}

spath with a path runs json_extract, one of seven json functions with no operand type check.

Each column is its own index with one document, where f is mapped to the column's type. f holds the JSON string {"a": "x"} for keyword, 5 for long, 1.5 for double, true for boolean, 1.2.3.4 for ip, {"a": "x"} for object and flat_object, and [{"a": "x"}] for nested.

Command keyword long double boolean ip object flat_object nested
spath input=f a 200 500 500 500 500 500 500 500
json_extract(f, 'a') 200 500 500 500 500 500 500 500
json_set(f, 'a', '1') 200 500 500 500 500 500 500 500
json_append(f, 'a', '1') 200 500 500 500 500 500 500 500
json_extend(f, 'a', '1') 200 500 500 500 500 500 500 500
json_keys(f) 200 200, null 200, null 200, null 500 500 500 500
json_delete(f, 'a') 200 200, "5" 200, "1.5" 200, "true" 500 500 500 500
json(f) 200 500 500 500 200, null 200, null 200, null 200, null
spath input=f, for comparison 200 400 400 400 400 400 400 400
json_array_length(f), for comparison 200 400 400 400 400 400 400 400

Every 500 in the first five rows is a ClassCastException to String. The 500s from json_keys and json_delete are CalciteException Invalid input for JSON_KEYS and Invalid input for JSON_REMOVE. The 500s from json are the reverse cast, such as class java.lang.String cannot be cast to class java.lang.Long on long.

With plugins.calcite.pushdown.enabled=false the query still returns HTTP 500 with the same cast, reported as a RuntimeException whose message carries an SQLException prefix. With pushdown on, _explain shows JSON_EXTRACT in an EnumerableCalc above the index scan, and the pushed request only fetches f from _source, so OpenSearch core is not involved.

Node log for source=spx | spath input=n a
[ERROR][o.o.s.p.r.RestPPLQueryAction] Error happened during query handling (status INTERNAL_SERVER_ERROR)
org.opensearch.sql.common.error.ErrorReport: class java.lang.Long cannot be cast to class java.lang.String (java.lang.Long and java.lang.String are in module java.base of loader 'bootstrap')
	at org.opensearch.sql.executor.QueryService.executeCalcitePlan(QueryService.java:277)
Caused by: java.lang.ClassCastException: class java.lang.Long cannot be cast to class java.lang.String (java.lang.Long and java.lang.String are in module java.base of loader 'bootstrap')
	at org.opensearch.sql.expression.function.jsonUDF.JsonExtractFunctionImpl.eval(JsonExtractFunctionImpl.java:64)
	at org.opensearch.sql.opensearch.executor.OpenSearchExecutionEngine.buildResultSet(OpenSearchExecutionEngine.java:442)
	at org.opensearch.sql.opensearch.executor.OpenSearchExecutionEngine.lambda$execute$6(OpenSearchExecutionEngine.java:338)

Dataset Information

Dataset/Schema Type

  • OpenTelemetry (OTEL)
  • Simple Schema for Observability (SS4O)
  • Open Cybersecurity Schema Framework (OCSF)
  • Custom (details below)

Index Mapping

PUT spx { "mappings": { "properties": { "host": { "type": "keyword" }, "n": { "type": "long" }, "j": { "type": "keyword" } } } }

Sample Data

POST spx/_doc/1?refresh=true  { "host": "a", "n": 5, "j": "{\"a\": \"x\"}" }

Bug Description

Issue Summary

spath with a path is rewritten to json_extract in SPath. JsonExtractFunctionImpl.getOperandMetadata() returns null, so JSON_EXTRACT accepts any argument, and eval casts the first one with String jsonStr = (String) args[0];. json_set, json_append and json_extend also have null metadata and make the same cast. json_keys, json_delete and json have null metadata and call args[0].toString() instead. The result type of json is wrong as well. ReturnTypes.ARG0_FORCE_NULLABLE types it as the input type while eval returns a string, so a number or boolean input throws the reverse cast.

spath without a path runs json_extract_all, which declares a STRING operand checker, as json_array_length does. Both reject a non-string at analysis with an ExpressionEvaluationException, which SyncErrorReportRenderer.isClientError maps to 400. isClientError lists neither ClassCastException nor CalciteException, so the unchecked functions return 500.

Steps to Reproduce

curl -s -XPUT "localhost:9200/spx" -H 'Content-Type: application/json' \
  -d '{"mappings":{"properties":{"host":{"type":"keyword"},"n":{"type":"long"},"j":{"type":"keyword"}}}}'
curl -s -XPOST "localhost:9200/spx/_doc/1?refresh=true" -H 'Content-Type: application/json' \
  -d '{"host":"a","n":5,"j":"{\"a\": \"x\"}"}'

# 1. spath with a path on a long returns HTTP 500 ClassCastException
curl -s -XPOST "localhost:9200/_plugins/_ppl" -H 'Content-Type: application/json' \
  -d '{"query":"source=spx | spath input=n a"}' -w '\nHTTP %{http_code}\n'

# 2. json_extract on the same field returns the same HTTP 500
curl -s -XPOST "localhost:9200/_plugins/_ppl" -H 'Content-Type: application/json' \
  -d '{"query":"source=spx | eval x = json_extract(n, '\''a'\'') | fields x"}' -w '\nHTTP %{http_code}\n'

# 3. spath without a path on the same field is checked and returns HTTP 400
curl -s -XPOST "localhost:9200/_plugins/_ppl" -H 'Content-Type: application/json' \
  -d '{"query":"source=spx | spath input=n | fields host"}' -w '\nHTTP %{http_code}\n'

# 4. spath with a path on the JSON string returns HTTP 200
curl -s -XPOST "localhost:9200/_plugins/_ppl" -H 'Content-Type: application/json' \
  -d '{"query":"source=spx | spath input=j a | fields a"}' -w '\nHTTP %{http_code}\n'

Impact

spath pointed at a field mapped as a number or an object, such as an OTel attributes object, returns a 500 naming two Java classes instead of the type it needs. json_keys and json_delete on a number return a 200 that looks like a result.

Environment Information

OpenSearch Version: main at f36c99f84, 3.10.0-SNAPSHOT, one node, with the defaults plugins.calcite.enabled=true, plugins.calcite.pushdown.enabled=true and plugins.calcite.fallback.allowed=false.

Lingua principale
Java
Stelle
175
Fork
232
Merge medio
3g 3h
PR unite (30g)
42

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di opensearch-project/sql

Tutte le issue di opensearch-project/sql

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.