From ab85963cbd33c22cf311645fdfebb0bf6ceedf07 Mon Sep 17 00:00:00 2001 From: gillespi314 <73313222+gillespi314@users.noreply.github.com> Date: Mon, 11 Apr 2022 15:18:31 -0500 Subject: [PATCH] Handle UI error parsing invalid sql (#5016) --- frontend/hooks/usePlatformCompatibility.tsx | 17 ++++------ .../ManageQueriesPage/ManageQueriesPage.tsx | 7 ++-- .../components/QueryForm/QueryForm.tsx | 2 +- frontend/utilities/sql_tools.ts | 34 +++++++++++-------- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/frontend/hooks/usePlatformCompatibility.tsx b/frontend/hooks/usePlatformCompatibility.tsx index e75be59a07..87eedae041 100644 --- a/frontend/hooks/usePlatformCompatibility.tsx +++ b/frontend/hooks/usePlatformCompatibility.tsx @@ -20,20 +20,17 @@ const usePlatformCompatibility = (): IPlatformCompatibility => { >(null); const [error, setError] = useState(null); - const tryCheckCompatibility = (sqlStr: string) => { - try { - const platforms = checkPlatformCompatibility(sqlStr); - setCompatiblePlatforms(platforms); - setError(null); - return; - } catch (err: unknown) { - setError(new Error(`Invalid usage: ${err}`)); - } + const checkCompatibility = (sqlStr: string) => { + const { platforms, error: compatibilityError } = checkPlatformCompatibility( + sqlStr + ); + setCompatiblePlatforms(platforms || []); + setError(compatibilityError); }; const debounceCompatiblePlatforms = useDebouncedCallback( (queryString: string) => { - tryCheckCompatibility(queryString); + checkCompatibility(queryString); }, DEBOUNCE_DELAY, { leading: true, trailing: true } diff --git a/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx b/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx index 89df8df460..f4f2048b62 100644 --- a/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx +++ b/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx @@ -65,9 +65,12 @@ const PLATFORM_FILTER_OPTIONS = [ }, ]; -const getPlatforms = (queryString: string): IOsqueryPlatform[] => { - return checkPlatformCompatibility(queryString); +const getPlatforms = (queryString: string): Array => { + const { platforms } = checkPlatformCompatibility(queryString); + + return platforms || ["---"]; }; + const enhanceQuery = (q: IQuery) => { return { ...q, diff --git a/frontend/pages/queries/QueryPage/components/QueryForm/QueryForm.tsx b/frontend/pages/queries/QueryPage/components/QueryForm/QueryForm.tsx index 7737364ee0..96f9d7bb73 100644 --- a/frontend/pages/queries/QueryPage/components/QueryForm/QueryForm.tsx +++ b/frontend/pages/queries/QueryPage/components/QueryForm/QueryForm.tsx @@ -121,7 +121,7 @@ const QueryForm = ({ queryIdForEdit = queryIdForEdit || 0; useEffect(() => { - if (queryIdForEdit === lastEditedQueryId) { + if (!isStoredQueryLoading && queryIdForEdit === lastEditedQueryId) { setCompatiblePlatforms(lastEditedQueryBody); } diff --git a/frontend/utilities/sql_tools.ts b/frontend/utilities/sql_tools.ts index 93abcf9e79..8964c83628 100644 --- a/frontend/utilities/sql_tools.ts +++ b/frontend/utilities/sql_tools.ts @@ -28,8 +28,6 @@ interface IOsqueryTable { platforms: IOsqueryPlatform[]; } -export type IParserResult = Error | IOsqueryPlatform | string; - type IPlatformDictionay = Record; const platformsByTableDictionary: IPlatformDictionay = (osqueryTables as IOsqueryTable[]).reduce( @@ -67,9 +65,7 @@ const _visit = ( } }; -export const filterCompatiblePlatforms = ( - sqlTables: string[] -): IOsqueryPlatform[] => { +const filterCompatiblePlatforms = (sqlTables: string[]): IOsqueryPlatform[] => { if (!sqlTables.length) { return [...SUPPORTED_PLATFORMS]; // if a query has no tables but is still syntatically valid sql, it is treated as compatible with all platforms } @@ -83,7 +79,7 @@ export const filterCompatiblePlatforms = ( return SUPPORTED_PLATFORMS.filter((p) => compatiblePlatforms.includes(p)); }; -export const parseSqlTables = ( +const parseSqlTables = ( sqlString: string, includeCteTables = false ): string[] => { @@ -118,30 +114,38 @@ export const parseSqlTables = ( return results; } catch (err) { - // console.log(`Invalid query syntax: ${err.message}\n\n${sqlString}`); + // console.log(`sqlite-parser error: ${err}\n\n${sqlString}`); - throw err; // TODO + throw err; } }; -export const checkPlatformCompatibility = ( +const checkPlatformCompatibility = ( sqlString: string, includeCteTables = false -): IOsqueryPlatform[] => { +): { platforms: IOsqueryPlatform[] | null; error: Error | null } => { let sqlTables: string[] | undefined; try { sqlTables = parseSqlTables(sqlString, includeCteTables); } catch (err) { - throw err; + return { platforms: null, error: new Error(`${err}`) }; } if (sqlTables === undefined) { - throw new Error( - "Unexpected error checking platform compatibility: sqlTables are undefined" - ); + return { + platforms: null, + error: new Error( + "Unexpected error checking platform compatibility: sqlTables are undefined" + ), + }; } - return filterCompatiblePlatforms(sqlTables); + try { + const platforms = filterCompatiblePlatforms(sqlTables); + return { platforms, error: null }; + } catch (err) { + return { platforms: null, error: new Error(`${err}`) }; + } }; export default checkPlatformCompatibility;