generated from amazon-archives/__template_Custom
-
Notifications
You must be signed in to change notification settings - Fork 187
[Feature] fieldformat command implementation #5080
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
penghuo
merged 35 commits into
opensearch-project:main
from
asifabashar:feature-fieldformat
Feb 11, 2026
Merged
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
ad84a10
fielfformat changes
asifabashar e956256
added field format with concatenation of string , added more examples
asifabashar fee4033
added field format with concatenation of string , added more examples
asifabashar 3aa3ea2
ci failure fix test
asifabashar d7edefb
ci failure fix test
asifabashar 3991f4f
ci failure fix test
asifabashar 95235de
ci failure fix test
asifabashar 018050d
added missing test files
asifabashar b9081d6
added missing test files
asifabashar 0b4981a
doc fix
asifabashar 0a9808f
doc fix
asifabashar f33269b
doc fix
asifabashar caabe38
added test
asifabashar 3fdf753
[Feature] implement transpose command as in the roadmap #4786 (#5011)
asifabashar d49d43a
added test
asifabashar 24b0b2f
[Feature] implement transpose command as in the roadmap #4786 (#5011)
asifabashar 186b33a
fielfformat changes
asifabashar 9c3c12a
added field format with concatenation of string , added more examples
asifabashar 8089974
added test
asifabashar a275205
[Feature] implement transpose command as in the roadmap #4786 (#5011)
asifabashar 517a57c
added test
asifabashar 9402c8e
merge from main
asifabashar 5a2d420
merge conflict issues
asifabashar 87adc88
doc fix
asifabashar e2d7cd8
test fix
asifabashar e64681f
test fix
asifabashar e1660e6
coderabbit recommendations
asifabashar dda54be
resolve conflicts
asifabashar de6ad4f
resolve conflicts
asifabashar 520dc9d
resolve conflicts
asifabashar 4d2eef3
resolve conflicts
asifabashar d33dd3a
removed ambigous sentence
asifabashar 8a56b47
added missing test files
asifabashar c9a322d
spotlessApply
asifabashar 520dbc4
merge conflict fix
asifabashar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
|
|
||
| # fieldformat | ||
|
|
||
| The `fieldformat` command sets the value to a field with the specified expression and appends the field with evaluated result to the search results. The command is an alias of eval command. | ||
| Additionally, it also provides string concatenation dot operator followed by and/or follows a string that will be concatenated to the expression. | ||
|
|
||
|
|
||
| ## Syntax | ||
|
|
||
| The `fieldformat` command has the following syntax: | ||
|
|
||
| ```syntax | ||
| fieldformat <field>=[(prefix).]<expression>[.(suffix)] ["," <field>=[(prefix).]<expression>[.(suffix)] ]... | ||
|
|
||
asifabashar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ## Parameters | ||
|
|
||
| The `fieldformat` command supports the following parameters. | ||
|
|
||
| | Parameter| Required/Optional | Description | | ||
| |----------------|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| | ||
| | `<field>` | Required | The name of the field to create or update. If the field does not exist, a new field is added. If it already exists, its value is overwritten. | | ||
| | `<expression>` | Required | The expression to evaluate. The expression can have a prefix and/or suffix string part that will be concatenated to the expression. | | ||
| | `prefix` | Optional | A string before the expression followed by dot operator which will be concatenated as prefix to the evaluated expression value. | | ||
| | `suffix` | Optional | A string that follows the expression and dot operator which will be concatenated as suffix to the evaluated expression value. | | ||
|
|
||
|
|
||
| ## Example 1: Create a new field | ||
|
|
||
| The following query creates a new `doubleAge` field for each document: | ||
|
|
||
| ```ppl | ||
| source=accounts | ||
| | fieldformat doubleAge = age * 2 | ||
| | fields age, doubleAge | ||
| ``` | ||
|
|
||
| The query returns the following results: | ||
|
|
||
| ```text | ||
| fetched rows / total rows = 4/4 | ||
| +-----+-----------+ | ||
| | age | doubleAge | | ||
| |-----+-----------| | ||
| | 32 | 64 | | ||
| | 36 | 72 | | ||
| | 28 | 56 | | ||
| | 33 | 66 | | ||
| +-----+-----------+ | ||
| ``` | ||
|
|
||
|
|
||
| ## Example 2: Override an existing field | ||
|
|
||
| The following query overrides the `age` field by adding `1` to its value: | ||
|
|
||
| ```ppl | ||
| source=accounts | ||
| | fieldformat age = age + 1 | ||
| | fields age | ||
| ``` | ||
|
|
||
| The query returns the following results: | ||
|
|
||
| ```text | ||
| fetched rows / total rows = 4/4 | ||
| +-----+ | ||
| | age | | ||
| |-----| | ||
| | 33 | | ||
| | 37 | | ||
| | 29 | | ||
| | 34 | | ||
| +-----+ | ||
| ``` | ||
|
|
||
|
|
||
|
|
||
|
|
||
| ## Example 3: String concatenation with prefix | ||
|
|
||
| The following query uses the `.` (dot) operator for string concatenation. You can concatenate string literals and field values as follows: | ||
|
|
||
| ```ppl | ||
| source=accounts | ||
| | fieldformat greeting = 'Hello '.tostring( firstname) | ||
| | fields firstname, greeting | ||
| ``` | ||
|
|
||
| The query returns the following results: | ||
|
|
||
| ```text | ||
| fetched rows / total rows = 4/4 | ||
| +-----------+---------------+ | ||
| | firstname | greeting | | ||
| |-----------+---------------| | ||
| | Amber | Hello Amber | | ||
| | Hattie | Hello Hattie | | ||
| | Nanette | Hello Nanette | | ||
| | Dale | Hello Dale | | ||
| +-----------+---------------+ | ||
| ``` | ||
|
|
||
|
|
||
| ## Example 4: String concatenation with dot operator, prefix and suffix | ||
|
|
||
| The following query performs prefix and suffix string concatenation operations using dot operator: | ||
|
|
||
| ```ppl | ||
| source=accounts | fieldformat age_info = 'Age: '.CAST(age AS STRING).' years.' | fields firstname, age, age_info | ||
| ``` | ||
|
|
||
| The query returns the following results: | ||
|
|
||
| ```text | ||
| fetched rows / total rows = 4/4 | ||
| +-----------+-----+----------------+ | ||
| | firstname | age | age_info | | ||
| |-----------+-----+----------------| | ||
| | Amber | 32 | Age: 32 years. | | ||
| | Hattie | 36 | Age: 36 years. | | ||
| | Nanette | 28 | Age: 28 years. | | ||
| | Dale | 33 | Age: 33 years. | | ||
| +-----------+-----+----------------+ | ||
| ``` | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteFieldFormatCommandIT.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.calcite.remote; | ||
|
|
||
| import static org.opensearch.sql.util.MatcherUtils.*; | ||
|
|
||
| import java.io.IOException; | ||
| import org.apache.commons.text.StringEscapeUtils; | ||
| import org.json.JSONObject; | ||
| import org.junit.jupiter.api.Test; | ||
asifabashar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import org.opensearch.client.Request; | ||
| import org.opensearch.sql.ppl.PPLIntegTestCase; | ||
|
|
||
| public class CalciteFieldFormatCommandIT extends PPLIntegTestCase { | ||
|
|
||
| @Override | ||
| public void init() throws Exception { | ||
| super.init(); | ||
| enableCalcite(); | ||
|
|
||
| loadIndex(Index.BANK); | ||
|
|
||
| // Create test data for string concatenation | ||
| Request request1 = new Request("PUT", "/test_eval/_doc/1?refresh=true"); | ||
| request1.setJsonEntity("{\"name\": \"Alice\", \"age\": 25, \"title\": \"Engineer\"}"); | ||
| client().performRequest(request1); | ||
|
|
||
| Request request2 = new Request("PUT", "/test_eval/_doc/2?refresh=true"); | ||
| request2.setJsonEntity("{\"name\": \"Bob\", \"age\": 30, \"title\": \"Manager\"}"); | ||
| client().performRequest(request2); | ||
|
|
||
| Request request3 = new Request("PUT", "/test_eval/_doc/3?refresh=true"); | ||
| request3.setJsonEntity("{\"name\": \"Charlie\", \"age\": null, \"title\": \"Analyst\"}"); | ||
| client().performRequest(request3); | ||
| } | ||
|
|
||
| @Test | ||
| public void testFieldFormatStringConcatenation() throws IOException { | ||
| JSONObject result = | ||
| executeQuery( | ||
| StringEscapeUtils.escapeJson( | ||
| "source=test_eval | fieldformat greeting = 'Hello ' + name")); | ||
| verifySchema( | ||
| result, | ||
| schema("name", "string"), | ||
| schema("title", "string"), | ||
| schema("age", "bigint"), | ||
| schema("greeting", "string")); | ||
| verifyDataRows( | ||
| result, | ||
| rows("Alice", "Engineer", 25, "Hello Alice"), | ||
| rows("Bob", "Manager", 30, "Hello Bob"), | ||
| rows("Charlie", "Analyst", null, "Hello Charlie")); | ||
| } | ||
|
|
||
| @Test | ||
| public void testFieldFormatStringConcatenationWithNullFieldToString() throws IOException { | ||
| JSONObject result = | ||
| executeQuery( | ||
| StringEscapeUtils.escapeJson( | ||
| "source=test_eval | fieldformat age_desc = \"Age: \".tostring(age,\"commas\") |" | ||
| + " fields name, age, age_desc")); | ||
| verifySchema( | ||
| result, schema("name", "string"), schema("age", "bigint"), schema("age_desc", "string")); | ||
| verifyDataRows( | ||
| result, | ||
| rows("Alice", 25, "Age: 25"), | ||
| rows("Bob", 30, "Age: 30"), | ||
| rows("Charlie", null, null)); | ||
asifabashar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| @Test | ||
| public void testFieldFormatStringConcatenationWithNullField() throws IOException { | ||
| JSONObject result = | ||
| executeQuery( | ||
| StringEscapeUtils.escapeJson( | ||
| "source=test_eval | fieldformat age_desc = \"Age: \".CAST(age AS STRING) | fields" | ||
| + " name, age, age_desc")); | ||
| verifySchema( | ||
| result, schema("name", "string"), schema("age", "bigint"), schema("age_desc", "string")); | ||
| verifyDataRows( | ||
| result, | ||
| rows("Alice", 25, "Age: 25"), | ||
| rows("Bob", 30, "Age: 30"), | ||
| rows("Charlie", null, null)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testFieldFormatStringConcatWithSuffix() throws IOException { | ||
| JSONObject result = | ||
| executeQuery( | ||
| StringEscapeUtils.escapeJson( | ||
| "source=test_eval | fieldformat age_desc = CAST(age AS STRING).\" years\" | fields" | ||
| + " name, age, age_desc")); | ||
| verifySchema( | ||
| result, schema("name", "string"), schema("age", "bigint"), schema("age_desc", "string")); | ||
| verifyDataRows( | ||
| result, | ||
| rows("Alice", 25, "25 years"), | ||
| rows("Bob", 30, "30 years"), | ||
| rows("Charlie", null, null)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testFieldFormatStringConcatWithPrefixSuffix() throws IOException { | ||
| JSONObject result = | ||
| executeQuery( | ||
| StringEscapeUtils.escapeJson( | ||
| "source=test_eval | fieldformat age_desc = \"Age: \".CAST(age AS STRING).\" years\"" | ||
| + " | fields name, age, age_desc")); | ||
| verifySchema( | ||
| result, schema("name", "string"), schema("age", "bigint"), schema("age_desc", "string")); | ||
| verifyDataRows( | ||
| result, | ||
| rows("Alice", 25, "Age: 25 years"), | ||
| rows("Bob", 30, "Age: 30 years"), | ||
| rows("Charlie", null, null)); | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.