Skip to content
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

[Auto Suggest] PPL & SQL Value Suggestion #8275

Merged

Conversation

paulstn
Copy link
Contributor

@paulstn paulstn commented Sep 20, 2024

Description

Only done for opensearch SQL + PPL. For both languages, value completion only occurs inside of a binary comparison predicate (for example column = value, and for an in-predicate with the keyword IN (e.g. column IN ("value1", "value2", "value3")). These are the only cases in which it makes sense to suggest values for a particular column.

SQL:

Screen.Recording.2024-10-09.at.11.51.51.AM.mov

PPL:

Screen.Recording.2024-10-09.at.11.42.04.AM.mov

src/plugins/data/public/antlr/*

For PPL & SQL, uses the SQL query

SELECT <column> FROM <table> GROUP BY <column> ORDER BY COUNT(<column>) DESC LIMIT <limit>

to find the most popular column values to display within autocomplete whenever a value should be suggested.

src/plugins/data/server/ui_settings.ts

There were two UI settings added.
query:enhancements:suggestValues is a boolean that determines if value suggestion will be used
query:enhancements:suggestValuesLimit is a number that specifies how many values should be queried, defaulting to 200

src/plugins/data/public/autocomplete/autocomplete_service.ts

The ability to add a value suggestion provided was included in this pr, but isn't in use so far. Creating a value suggestion provider that would make the api call (with all of the same parameters that exist right now) could be done but would require a lot of complexity for what is essentially done in 10 lines today.

This PR also contains various fixes and quality of life updates within SQL & PPL suggestions.

Issues Resolved

Screenshot

Testing the changes

Field level security testing:

Screen.Recording.2024-10-21.at.2.22.46.PM.mov

Field level masking testing:

Screen.Recording.2024-10-21.at.2.09.44.PM.mov

Changelog

  • feat: Autocomplete Value Suggestion

Check List

  • All tests pass
    • yarn test:jest
    • yarn test:jest_integration
  • New functionality includes testing.
  • New functionality has been documented.
  • Update CHANGELOG.md
  • Commits are signed per the DCO using --signoff

Copy link
Contributor

❌ Empty Changelog Section

The Changelog section in your PR description is empty. Please add a valid changelog entry or entries. If you did add a changelog entry, check to make sure that it was not accidentally included inside the comment block in the Changelog section.

Copy link

codecov bot commented Sep 20, 2024

Codecov Report

Attention: Patch coverage is 75.44910% with 41 lines in your changes missing coverage. Please review.

Project coverage is 61.61%. Comparing base (82689bb) to head (26782e2).
Report is 24 commits behind head on main.

Files with missing lines Patch % Lines
...ntlr/opensearch_sql/opensearch_sql_autocomplete.ts 68.62% 12 Missing and 4 partials ⚠️
...ntlr/opensearch_ppl/opensearch_ppl_autocomplete.ts 63.88% 7 Missing and 6 partials ⚠️
...ata/public/antlr/opensearch_sql/code_completion.ts 78.78% 3 Missing and 4 partials ⚠️
...ugins/data/public/ui/query_editor/query_editor.tsx 0.00% 3 Missing ⚠️
...ata/public/antlr/opensearch_ppl/code_completion.ts 81.81% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8275      +/-   ##
==========================================
+ Coverage   61.01%   61.61%   +0.59%     
==========================================
  Files        3812     3813       +1     
  Lines       91385    91610     +225     
  Branches    14438    14498      +60     
==========================================
+ Hits        55762    56441     +679     
+ Misses      32065    31587     -478     
- Partials     3558     3582      +24     
Flag Coverage Δ
Linux_1 29.00% <5.48%> (-0.08%) ⬇️
Linux_2 ?
Linux_3 39.08% <75.44%> (+1.05%) ⬆️
Linux_4 28.93% <5.48%> (-0.10%) ⬇️
Windows_1 29.01% <5.48%> (-0.08%) ⬇️
Windows_2 56.40% <ø> (+<0.01%) ⬆️
Windows_3 39.08% <75.44%> (+1.06%) ⬆️
Windows_4 28.93% <5.48%> (-0.10%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@paulstn paulstn force-pushed the autosuggest-value-suggestion branch from 4bb08f5 to 603a1d9 Compare December 19, 2024 22:22
});
});

it.skip('should suggest aggregate functions when appropriate', async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: This test is skipped for now due to the working functionality requiring a new 'rerun and combine' functionality, where preferred rules are removed one at a time and then the completion candidate process is run without that rule.
This new system is already written in this PR: #9120
Decoupling it from the rest of that PR would be too much unnecessary effort.

Copy link
Collaborator

@mengweieric mengweieric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need more time to test it in app.

});

describe('processVisitedRules', () => {
// // createTokenStream takes a list of 'tokens' defined only by its type or an actual object to be returned as the Token
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we remove these commented out tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left this in as an accident, I was going to write these tests but I was able to cover these tests with end to end tests in code_completion.test.ts.
I'll put some basic processVisitedRules tests in just as a placeholder if more testing is needed for PPL's visitedRules

src/plugins/data/public/antlr/shared/utils.ts Outdated Show resolved Hide resolved
export type ValueSuggestionsGetFn = (args: ValueSuggestionsGetFnArgs) => Promise<any[]>;
export type ValueSuggestionsGetFn = (
args: ValueSuggestionsGetFnArgs | ValueSuggestionsSQLGetFnArgs
) => Promise<any[]>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what @joshuali925 suggests is to make ValueSuggestionsGetFn generic by parameterizing args and return types to look something like:

export type ValueSuggestionsGetFn<ArgsType = any, ReturnType = any[]> = (
  args: ArgsType
) => Promise<ReturnType>;

with this refactoring, for different types of languages you can now use it to be something like

const sqlValueSuggestions: ValueSuggestionsGetFn<ValueSuggestionsSQLGetFnArgs, string[]> = async (args) => {
  // Implementation specific to SQL
  return ['value1', 'value2'];
};

const otherLanguageSuggestions: ValueSuggestionsGetFn<CustomArgsType, CustomReturnType> = async (args) => {
  // Implementation for another language
  return [{ id: 1, name: 'value1' }];
};

return provider(args);
}
}
return this.defaultGetValueSuggestions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a question: what would be a valid use case where we don't have an autocomplete provider for a language? If this is the case, should we even provide the default provider as default provider may not even be the one works with this language?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default value provider exists for the discover filter bar, i've set the default like that because i'm aiming to make it so that it will still exist for every case other than if the language is sql/ppl

@@ -263,7 +263,7 @@ export const QueryEditorUI: React.FC<Props> = (props) => {
range: s.replacePosition ?? defaultRange,
detail: s.detail,
command: { id: 'editor.action.triggerSuggest', title: 'Trigger Next Suggestion' },
sortText: s.sortText, // when undefined, the falsy value will default to the label
sortText: s.sortText ?? s.text, // when undefined, the falsy value will default to the label
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will s.text also be undefined or null in corner cases? do we want something like

sortText: s.sortText ?? s.text ?? ""

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s.text can't be undefined or null because its type (MonacoCompatibleQuerySuggestion) has text as a required field

column: string,
services: IDataPluginServices,
fieldInOsd: IndexPatternField | undefined
): Promise<any[]> => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like we can use string[] as the return type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally wrote this to return a string array, but I changed it to any because if the value suggestions change in the future and return more types than just string, this method would be able to handle those cases too.
Should I change it back to string[]?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be able to follow the similar above: #8275 (comment), or if string is the only type supported as of right now we can stick with string and extend it later when we want dynamic typing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to this in an earlier commit, agree with extending it later since currently only string is supported

src/plugins/data/public/antlr/shared/utils.ts Outdated Show resolved Hide resolved
);
})
)
).body.fields[0].values;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line of code will fail if any field in this chain is missing is it? Also seems like fetchFromAPI is rejecting the promise when there's issue, is this case handled correctly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case when fetchFromAPI rejects the promise with the error, the rejected promise will travel up to the caller of fetchColumnValues. I wrote a test for this mocking an error from the http fetch function that fetchFromAPI calls:
https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8275/files/2a167e91cc27b7be0091cd010495ed87ef9cd0e7#diff-b547688af7b19722a725a97405371301f010a16e1d6dd8dfbfdae74b0e3c784eR374-R382

In the case where the fetched object doesn't match this caller chain, it will throw a rejected promise about the format. I wrote it this way because currently the returned object has this exact format, and there is no other standard to flatted this object to that I'm aware of.

@paulstn paulstn force-pushed the autosuggest-value-suggestion branch from 2a167e9 to 0a0ae50 Compare January 6, 2025 23:19
@paulstn paulstn mentioned this pull request Jan 8, 2025
7 tasks
@joshuali925 joshuali925 merged commit a7aeb76 into opensearch-project:main Jan 17, 2025
69 checks passed
@opensearch-trigger-bot
Copy link
Contributor

The backport to 2.x failed:

The process '/usr/bin/git' failed with exit code 128

To backport manually, run these commands in your terminal:

# Navigate to the root of your repository
cd $(git rev-parse --show-toplevel)
# Fetch latest updates from GitHub
git fetch
# Create a new working tree
git worktree add ../.worktrees/OpenSearch-Dashboards/backport-2.x 2.x
# Navigate to the new working tree
pushd ../.worktrees/OpenSearch-Dashboards/backport-2.x
# Create a new branch
git switch --create backport/backport-8275-to-2.x
# Cherry-pick the merged commit of this pull request and resolve the conflicts
git cherry-pick -x --mainline 1 a7aeb76b70b79880ff807895df3bb5cc19eb1178
# Push it to GitHub
git push --set-upstream origin backport/backport-8275-to-2.x
# Go back to the original working tree
popd
# Delete the working tree
git worktree remove ../.worktrees/OpenSearch-Dashboards/backport-2.x

Then, create a pull request where the base branch is 2.x and the compare/head branch is backport/backport-8275-to-2.x.

opensearch-trigger-bot bot pushed a commit that referenced this pull request Jan 21, 2025
Signed-off-by: Paul Sebastian <[email protected]>
Signed-off-by: Paul Sebastian <[email protected]>
Co-authored-by: Paul Sebastian <[email protected]>
Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
(cherry picked from commit a7aeb76)
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants