Skip to content

Commit 053edf5

Browse files
committed
Merge remote-tracking branch 'origin/main' into issues/4580
2 parents 3cae4b8 + c30d5d0 commit 053edf5

29 files changed

Lines changed: 850 additions & 273 deletions

File tree

.github/workflows/maven-publish.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ on:
88
- '[0-9]+.[0-9]+'
99
- '[0-9]+.x'
1010

11-
env:
12-
SNAPSHOT_REPO_URL: https://ci.opensearch.org/ci/dbc/snapshots/maven/
13-
1411
jobs:
1512
build-and-publish-snapshots:
1613
strategy:

.github/workflows/publish-async-query-core.yml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ on:
55
push:
66
branches:
77
- main
8-
- 1.*
9-
- 2.*
8+
- '[0-9]+.[0-9]+'
9+
- '[0-9]+.x'
1010
paths:
1111
- 'async-query-core/**'
1212
- '.github/workflows/publish-async-query-core.yml'
@@ -18,7 +18,6 @@ concurrency:
1818
cancel-in-progress: false
1919

2020
env:
21-
SNAPSHOT_REPO_URL: https://central.sonatype.com/repository/maven-snapshots/
2221
COMMIT_MAP_FILENAME: commit-history-async-query-core.json
2322

2423
jobs:
@@ -47,8 +46,19 @@ jobs:
4746
export-env: true
4847
env:
4948
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
50-
SONATYPE_USERNAME: op://opensearch-infra-secrets/maven-central-portal-credentials/username
51-
SONATYPE_PASSWORD: op://opensearch-infra-secrets/maven-central-portal-credentials/password
49+
MAVEN_SNAPSHOTS_S3_REPO: op://opensearch-infra-secrets/maven-snapshots-s3/repo
50+
MAVEN_SNAPSHOTS_S3_ROLE: op://opensearch-infra-secrets/maven-snapshots-s3/role
51+
52+
- name: Export SNAPSHOT_REPO_URL
53+
run: |
54+
snapshot_repo_url=${{ env.MAVEN_SNAPSHOTS_S3_REPO }}
55+
echo "SNAPSHOT_REPO_URL=$snapshot_repo_url" >> $GITHUB_ENV
56+
57+
- name: Configure AWS credentials
58+
uses: aws-actions/configure-aws-credentials@v5
59+
with:
60+
role-to-assume: ${{ env.MAVEN_SNAPSHOTS_S3_ROLE }}
61+
aws-region: us-east-1
5262

5363
- name: Set commit ID
5464
id: set_commit
@@ -83,4 +93,4 @@ jobs:
8393
source ./.github/maven-publish-utils.sh
8494
8595
# Call the main function for async-query-core
86-
publish_async_query_core "${{ steps.extract_version.outputs.VERSION }}" "${{ steps.set_commit.outputs.commit_id }}"
96+
publish_async_query_core "${{ steps.extract_version.outputs.VERSION }}" "${{ steps.set_commit.outputs.commit_id }}"

.github/workflows/publish-grammar-files.yml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ on:
55
push:
66
branches:
77
- main
8-
- 1.*
9-
- 2.*
8+
- '[0-9]+.[0-9]+'
9+
- '[0-9]+.x'
1010
paths:
1111
- 'language-grammar/src/main/antlr4/**'
1212
- 'language-grammar/build.gradle'
@@ -19,7 +19,6 @@ concurrency:
1919
cancel-in-progress: false
2020

2121
env:
22-
SNAPSHOT_REPO_URL: https://central.sonatype.com/repository/maven-snapshots/
2322
COMMIT_MAP_FILENAME: commit-history-language-grammar.json
2423

2524
jobs:
@@ -51,8 +50,19 @@ jobs:
5150
export-env: true
5251
env:
5352
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
54-
SONATYPE_USERNAME: op://opensearch-infra-secrets/maven-central-portal-credentials/username
55-
SONATYPE_PASSWORD: op://opensearch-infra-secrets/maven-central-portal-credentials/password
53+
MAVEN_SNAPSHOTS_S3_REPO: op://opensearch-infra-secrets/maven-snapshots-s3/repo
54+
MAVEN_SNAPSHOTS_S3_ROLE: op://opensearch-infra-secrets/maven-snapshots-s3/role
55+
56+
- name: Export SNAPSHOT_REPO_URL
57+
run: |
58+
snapshot_repo_url=${{ env.MAVEN_SNAPSHOTS_S3_REPO }}
59+
echo "SNAPSHOT_REPO_URL=$snapshot_repo_url" >> $GITHUB_ENV
60+
61+
- name: Configure AWS credentials
62+
uses: aws-actions/configure-aws-credentials@v5
63+
with:
64+
role-to-assume: ${{ env.MAVEN_SNAPSHOTS_S3_ROLE }}
65+
aws-region: us-east-1
5666

5767
- name: Set version
5868
id: set_version

core/src/main/java/org/opensearch/sql/ast/dsl/AstDSL.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import org.opensearch.sql.ast.tree.Trendline;
8181
import org.opensearch.sql.ast.tree.UnresolvedPlan;
8282
import org.opensearch.sql.ast.tree.Values;
83+
import org.opensearch.sql.calcite.plan.OpenSearchConstants;
8384

8485
/** Class of static methods to create specific node instances. */
8586
@UtilityClass
@@ -491,15 +492,19 @@ public static Span spanFromSpanLengthLiteral(
491492
UnresolvedExpression field, Literal spanLengthLiteral) {
492493
if (spanLengthLiteral.getType() == DataType.STRING) {
493494
String spanText = spanLengthLiteral.getValue().toString();
494-
String valueStr = spanText.replaceAll("[^0-9]", "");
495-
String unitStr = spanText.replaceAll("[0-9]", "");
495+
String valueStr = spanText.replaceAll("[^0-9-]", "");
496+
String unitStr = spanText.replaceAll("[0-9-]", "");
496497

497498
if (valueStr.isEmpty()) {
498499
// No numeric value found, use the literal as-is
499500
return new Span(field, spanLengthLiteral, SpanUnit.NONE);
500501
} else {
501502
// Parse numeric value and unit
502503
Integer value = Integer.parseInt(valueStr);
504+
if (value <= 0) {
505+
throw new IllegalArgumentException(
506+
String.format("Zero or negative time interval not supported: %s", spanText));
507+
}
503508
SpanUnit unit = unitStr.isEmpty() ? SpanUnit.NONE : SpanUnit.of(unitStr);
504509
return span(field, intLiteral(value), unit);
505510
}
@@ -713,4 +718,9 @@ public static Bin bin(UnresolvedExpression field, Argument... arguments) {
713718
return DefaultBin.builder().field(field).alias(alias).build();
714719
}
715720
}
721+
722+
/** Get a reference to the implicit timestamp field {@code @timestamp} */
723+
public static Field referImplicitTimestampField() {
724+
return AstDSL.field(OpenSearchConstants.IMPLICIT_FIELD_TIMESTAMP);
725+
}
716726
}

core/src/main/java/org/opensearch/sql/ast/statement/Explain.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ public enum ExplainFormat {
3939
SIMPLE,
4040
STANDARD,
4141
EXTENDED,
42-
COST
42+
COST,
43+
/** Formats explain output in yaml format. */
44+
YAML
4345
}
4446

4547
public static ExplainFormat format(String format) {

core/src/main/java/org/opensearch/sql/executor/ExecutionEngine.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,22 @@ public boolean equals(Object o) {
109109
public int hashCode() {
110110
return Objects.hash(root, calcite);
111111
}
112+
113+
public static ExplainResponse normalizeLf(ExplainResponse response) {
114+
ExecutionEngine.ExplainResponseNodeV2 calcite = response.getCalcite();
115+
if (calcite != null) {
116+
return new ExplainResponse(
117+
new ExecutionEngine.ExplainResponseNodeV2(
118+
normalizeLf(calcite.getLogical()),
119+
normalizeLf(calcite.getPhysical()),
120+
normalizeLf(calcite.getExtended())));
121+
}
122+
return response;
123+
}
124+
125+
private static String normalizeLf(String value) {
126+
return value == null ? null : value.replace("\r\n", "\n");
127+
}
112128
}
113129

114130
@AllArgsConstructor

core/src/main/java/org/opensearch/sql/executor/QueryService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ public void explainWithLegacy(
201201
Explain.ExplainFormat format,
202202
Optional<Throwable> calciteFailure) {
203203
try {
204-
if (format != null && format != Explain.ExplainFormat.STANDARD) {
204+
if (format != null
205+
&& (format != Explain.ExplainFormat.STANDARD && format != Explain.ExplainFormat.YAML)) {
205206
throw new UnsupportedOperationException(
206207
"Explain mode " + format.name() + " is not supported in v2 engine");
207208
}

core/src/main/java/org/opensearch/sql/utils/YamlFormatter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
package org.opensearch.sql.utils;
77

8+
import com.fasterxml.jackson.annotation.JsonInclude;
89
import com.fasterxml.jackson.core.JsonProcessingException;
910
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import com.fasterxml.jackson.databind.SerializationFeature;
1012
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
1113
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
1214

@@ -21,11 +23,16 @@ public class YamlFormatter {
2123
static {
2224
YAMLFactory yamlFactory = new YAMLFactory();
2325
yamlFactory.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
26+
yamlFactory.enable(YAMLGenerator.Feature.USE_PLATFORM_LINE_BREAKS);
27+
yamlFactory.enable(YAMLGenerator.Feature.LITERAL_BLOCK_STYLE);
2428
yamlFactory.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES); // Enable smart quoting
2529
yamlFactory.enable(
2630
YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS); // Quote numeric strings
2731
yamlFactory.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR);
2832
YAML_MAPPER = new ObjectMapper(yamlFactory);
33+
34+
YAML_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
35+
YAML_MAPPER.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
2936
}
3037

3138
/**

docs/category.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"bash": [
3-
"user/ppl/interfaces/endpoint.rst",
4-
"user/ppl/interfaces/protocol.rst",
53
"user/optimization/optimization.rst",
64
"user/admin/settings.rst"
75
],
8-
"ppl_cli": [
6+
"bash_calcite": [
7+
"user/ppl/interfaces/endpoint.rst",
8+
"user/ppl/interfaces/protocol.rst"
99
],
1010
"sql_cli": [
1111
"user/dql/expressions.rst",

docs/user/ppl/cmd/stats.rst

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ stats [bucket_nullable=bool] <aggregation>... [by-clause]
5858

5959
* span-expression: optional, at most one.
6060

61-
* Syntax: span(field_expr, interval_expr)
62-
* Description: The unit of the interval expression is the natural unit by default. **If the field is a date/time type field, the aggregation results always ignore null bucket**. And the interval is in date/time units, you will need to specify the unit in the interval expression. For example, to split the field ``age`` into buckets by 10 years, it looks like ``span(age, 10)``. And here is another example of time span, the span to split a ``timestamp`` field into hourly intervals, it looks like ``span(timestamp, 1h)``.
61+
* Syntax: span([field_expr,] interval_expr)
62+
* Description: The unit of the interval expression is the natural unit by default. If ``field_expr`` is omitted, span will use the implicit ``@timestamp`` field. An error will be thrown if this field doesn't exist. **If the field is a date/time type field, the aggregation results always ignore null bucket**. And the interval is in date/time units, you will need to specify the unit in the interval expression. For example, to split the field ``age`` into buckets by 10 years, it looks like ``span(age, 10)``. And here is another example of time span, the span to split a ``timestamp`` field into hourly intervals, it looks like ``span(timestamp, 1h)``.
6363
* Available time unit:
6464

6565
+----------------------------+
@@ -580,7 +580,7 @@ Description
580580

581581
Version: 3.3.0 (Calcite engine only)
582582

583-
Usage: LIST(expr). Collects all values from the specified expression into an array. Values are converted to strings, nulls are filtered, and duplicates are preserved.
583+
Usage: LIST(expr). Collects all values from the specified expression into an array. Values are converted to strings, nulls are filtered, and duplicates are preserved.
584584
The function returns up to 100 values with no guaranteed ordering.
585585

586586
* expr: The field expression to collect values from.
@@ -977,3 +977,18 @@ PPL query::
977977
| 1 | 2025-01-01 | 2 |
978978
+-----+------------+--------+
979979

980+
981+
Example 18: Calculate the count by the implicit @timestamp field
982+
================================================================
983+
984+
This example demonstrates that if you omit the field parameter in the span function, it will automatically use the implicit ``@timestamp`` field.
985+
986+
PPL query::
987+
988+
PPL> source=big5 | stats count() by span(1month)
989+
fetched rows / total rows = 1/1
990+
+---------+---------------------+
991+
| count() | span(1month) |
992+
|---------+---------------------|
993+
| 1 | 2023-01-01 00:00:00 |
994+
+---------+---------------------+

0 commit comments

Comments
 (0)