From 681cc2fce78ac823eadb2c1b032ca582d27c235f Mon Sep 17 00:00:00 2001 From: Matej Kubinec Date: Fri, 3 Feb 2023 13:13:50 +0100 Subject: [PATCH 1/3] PMM-10893 Add basic handling for postgres explain --- .../panel/components/Details/Details.hooks.ts | 5 +-- .../panel/components/Details/Details.tsx | 2 +- .../Details/Explain/Explain.tools.ts | 24 ++++++++++- .../ExplainPlaceholders.tsx | 2 +- .../PlaceholdersForm/PlaceholdersForm.tsx | 5 ++- .../PlaceholdersForm.types.ts | 3 +- .../PlaceholdersForm.utils.ts | 13 ++++-- .../QueryFingerprint.test.tsx | 7 ++-- .../QueryFingerprint/QueryFingerprint.tsx | 4 +- .../QueryFingerprint.types.ts | 3 ++ .../QueryFingerprint.utils.ts | 40 ++++++++++++++++--- .../database-models/postgresql/postgresql.ts | 10 +++++ .../postgresql/postgresql.types.ts | 18 +++++++++ .../database-models/postgresql/service.ts | 7 ++++ 14 files changed, 118 insertions(+), 25 deletions(-) create mode 100644 pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts diff --git a/pmm-app/src/pmm-qan/panel/components/Details/Details.hooks.ts b/pmm-app/src/pmm-qan/panel/components/Details/Details.hooks.ts index 2805c31739..2f0d026562 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/Details.hooks.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/Details.hooks.ts @@ -1,10 +1,9 @@ import { useContext, useEffect, useState } from 'react'; import { QueryAnalyticsProvider } from 'pmm-qan/panel/provider/provider'; -import { Databases } from 'shared/core'; import DetailsService from './Details.service'; import { DatabasesType, QueryExampleResponseItem } from './Details.types'; -export const useDetails = (): [boolean, QueryExampleResponseItem[], DatabasesType] => { +export const useDetails = (): [boolean, QueryExampleResponseItem[], DatabasesType | undefined] => { const { panelState: { queryId, groupBy, from, to, labels, @@ -12,7 +11,7 @@ export const useDetails = (): [boolean, QueryExampleResponseItem[], DatabasesTyp } = useContext(QueryAnalyticsProvider); const [loading, setLoading] = useState(false); const [examples, setExamples] = useState([]); - const [databaseType, setDatabaseType] = useState(Databases.mysql); + const [databaseType, setDatabaseType] = useState(); useEffect(() => { (async () => { diff --git a/pmm-app/src/pmm-qan/panel/components/Details/Details.tsx b/pmm-app/src/pmm-qan/panel/components/Details/Details.tsx index e456b74a7d..1a9ffcf676 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/Details.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/Details.tsx @@ -35,7 +35,7 @@ export const DetailsSection: FC = () => { const [activeTab, changeActiveTab] = useState(TabKeys[openDetailsTab]); const showTablesTab = databaseType !== Databases.mongodb && groupBy === 'queryid' && !totals; - const showExplainTab = databaseType !== Databases.postgresql && groupBy === 'queryid' && !totals; + const showExplainTab = groupBy === 'queryid' && !totals; const showExamplesTab = groupBy === 'queryid' && !totals; const showPlanTab = databaseType === Databases.postgresql && groupBy === 'queryid' && !totals; diff --git a/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts b/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts index 1d19e63875..dc0d6d5d62 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts @@ -1,7 +1,7 @@ import { logger } from 'shared/core/logger'; import { ActionResult, getActionResult } from 'shared/components/Actions'; import { Databases } from 'shared/core'; -import { mongodbMethods, mysqlMethods } from '../database-models'; +import { mongodbMethods, mysqlMethods, postgresqlMethods } from '../database-models'; import { DatabasesType, QueryExampleResponseItem } from '../Details.types'; import { ClassicExplainInterface, FetchExplainsResult } from './Explain.types'; @@ -69,7 +69,27 @@ export const fetchExplains = async ( placeholders?: string[], ): Promise => { try { - if (databaseType === Databases.mysql && (placeholders || !example.placeholders_count)) { + const hasPlaceholders = placeholders || !example.placeholders_count; + + if (databaseType === Databases.postgresql && hasPlaceholders) { + const payload = { + serviceId: example.service_id, + queryId, + placeholders: placeholders || [], + }; + + const explain = await postgresqlMethods.getExplain(payload).then(getActionResult); + + const classicExplain = parseExplain(explain); + + return { + jsonExplain: actionResult, + classicExplain: { ...explain, value: classicExplain }, + visualExplain: actionResult, + }; + } + + if (databaseType === Databases.mysql && hasPlaceholders) { const payload = { example, queryId, diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx index 9904a31932..8fca1536a6 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx @@ -55,7 +55,7 @@ const ExplainPlaceholders: React.FC = ({ }; if (!initialized && example) { - return ; + return ; } return ( diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.tsx b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.tsx index cc165f0dce..e9f5933fe6 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.tsx @@ -10,12 +10,12 @@ import { getStyles } from './PlaceholdersForm.styles'; import { PlaceholdersFormProps, PlaceholdersFormValues } from './PlaceholdersForm.types'; import { prepareInputs } from './PlaceholdersForm.utils'; -const PlaceholdersForm: React.FC = ({ onSubmit, example }) => { +const PlaceholdersForm: React.FC = ({ database, onSubmit, example }) => { // recreate initial values if example changes to reset the form // eslint-disable-next-line react-hooks/exhaustive-deps const initialValues = useMemo(() => ({ placeholders: [] }), [example]); const styles = useStyles(getStyles); - const placeholders = prepareInputs(example.placeholders_count || 0); + const placeholders = prepareInputs(example.placeholders_count || 0, database); return (
@@ -24,6 +24,7 @@ const PlaceholdersForm: React.FC = ({ onSubmit, example }
{Messages.follow}
diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.types.ts b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.types.ts index b5d5343876..c11367de72 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.types.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.types.ts @@ -1,6 +1,7 @@ -import { QueryExampleResponseItem } from 'pmm-qan/panel/components/Details/Details.types'; +import { DatabasesType, QueryExampleResponseItem } from 'pmm-qan/panel/components/Details/Details.types'; export interface PlaceholdersFormProps { + database: DatabasesType; example: QueryExampleResponseItem; onSubmit: (values: PlaceholdersFormValues) => void; } diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.utils.ts b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.utils.ts index f8059043bb..9c1ed93b75 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.utils.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/PlaceholdersForm/PlaceholdersForm.utils.ts @@ -1,7 +1,12 @@ import { times } from 'lodash'; +import { DatabasesType } from '../../Details.types'; import { PlaceholderInput } from './PlaceholdersForm.types'; -export const prepareInputs = (count: number): PlaceholderInput[] => times(count, (idx) => ({ - label: `:${idx + 1}`, - fieldName: `placeholders.${idx}`, -})); +export const prepareInputs = (count: number, database: DatabasesType): PlaceholderInput[] => times( + count, (idx) => ({ + label: getPlaceholder(idx, database), + fieldName: `placeholders.${idx}`, + }), +); + +export const getPlaceholder = (idx: number, database: DatabasesType) => (database === 'postgresql' ? `$${idx + 1}` : `:${idx + 1}`); diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.test.tsx b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.test.tsx index c53167dba1..fa15a9d21b 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.test.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.test.tsx @@ -43,23 +43,24 @@ where describe('QueryFingerprint component::', () => { it('renders with empty query', () => { - render(); + render(); expect(screen.getByTestId('highlight-code').textContent).toEqual(''); }); it('renders with query without placeholders', () => { - render(); + render(); expect(screen.getByTestId('highlight-code').textContent).toEqual(QUERY_WITHOUT_PLACEHOLDERS); }); it('renders with query with placeholders not filled out', () => { - render(); + render(); expect(screen.getByTestId('highlight-code').textContent).toEqual(QUERY_WITH_PLACEHOLDERS); }); it('renders with placeholders (string)', () => { render( , diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.tsx b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.tsx index 2a1d397cdf..94b74a01c4 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.tsx @@ -3,8 +3,8 @@ import { Highlight } from 'shared/components/Hightlight/Highlight'; import { QueryFingerprintProps } from './QueryFingerprint.types'; import { replacePlaceholders } from './QueryFingerprint.utils'; -const QueryFingerprint: React.FC = ({ fingerprint, placeholders }) => { - const formatted = replacePlaceholders(fingerprint, placeholders); +const QueryFingerprint: React.FC = ({ database, fingerprint, placeholders }) => { + const formatted = replacePlaceholders(database, fingerprint, placeholders); return ( diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.types.ts b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.types.ts index 7e977d48ae..880c0a74a1 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.types.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.types.ts @@ -1,4 +1,7 @@ +import { DatabasesType } from '../../Details.types'; + export interface QueryFingerprintProps { + database: DatabasesType; placeholders: string[]; fingerprint: string; } diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.utils.ts b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.utils.ts index 9e5e7979f3..350a38c8a7 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.utils.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/QueryFingerprint/QueryFingerprint.utils.ts @@ -1,17 +1,45 @@ import sqlFormatter from 'sql-formatter'; +import { DatabasesType } from '../../Details.types'; -export const replacePlaceholders = (fingerprint: string, placeholders: string[] = []): string => { +export const replacePlaceholders = ( + database: DatabasesType, + fingerprint: string, + placeholders: string[] = [], +): string => { let replaced = fingerprint || ''; placeholders.forEach((value, idx) => { - const fingerprintIdx = idx + 1; - - if (value && replaced.includes(`::${fingerprintIdx}`)) { - replaced = replaced.replace(new RegExp(`::${fingerprintIdx}`, 'g'), value); + if (value && replaced.includes(getPlaceholderArray(database, idx))) { + replaced = replaced.replace(new RegExp(getPlaceholderArray(database, idx), 'g'), value); } else if (value) { - replaced = replaced.replace(new RegExp(`:${fingerprintIdx}`, 'g'), value); + replaced = replaced.replace(new RegExp(getPlaceholder(database, idx), 'g'), value); } }); return sqlFormatter.format(replaced); }; + +export const getPlaceholder = (database: DatabasesType, idx: number): string => { + if (database === 'mysql') { + return `:${idx + 1}`; + } + + if (database === 'postgresql') { + return `\\$${idx + 1}`; + } + + return ''; +}; + +export const getPlaceholderArray = (database: DatabasesType, idx: number): string => { + if (database === 'mysql') { + return `::${idx + 1}`; + } + + if (database === 'postgresql') { + // todo: check + return `\\$\\$${idx + 1}`; + } + + return ''; +}; diff --git a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts index 3d7494e80e..2a57ed3378 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts @@ -1,6 +1,16 @@ +import { PostgreSQLExplain } from './postgresql.types'; import PostgresqlDatabaseService from './service'; export const postgresqlMethods = { + getExplain: async ({ placeholders, queryId, serviceId }: PostgreSQLExplain): Promise => { + const result = await PostgresqlDatabaseService.getPostgreSQLExplain({ + queryId, + serviceId, + placeholders, + }); + + return result.action_id; + }, getShowCreateTables: async ({ example, tableName, database }) => { if (!tableName) { return null; diff --git a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts new file mode 100644 index 0000000000..0f5a5305e3 --- /dev/null +++ b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts @@ -0,0 +1,18 @@ +export interface PostgreSQLExplainBody { + pmmAgentId?: string; + serviceId: string; + queryId: string; + placeholders: string[]; + database?: string; +} + +export interface PostgreSQLExplainResponse { + action_id: string; + pmm_agent_id: string; +} + +export interface PostgreSQLExplain { + serviceId: string; + queryId: string; + placeholders: string[]; +} diff --git a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/service.ts b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/service.ts index d65c0bce5e..1d3c911c91 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/service.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/service.ts @@ -1,4 +1,5 @@ import { apiRequestManagement } from 'shared/components/helpers/api'; +import { PostgreSQLExplainBody, PostgreSQLExplainResponse } from './postgresql.types'; export default { getPostgreSQLIndex(body) { @@ -7,4 +8,10 @@ export default { getShowCreateTablePostgreSQL(body) { return apiRequestManagement.post('/Actions/StartPostgreSQLShowCreateTable', body); }, + getPostgreSQLExplain(body: PostgreSQLExplainBody) { + return apiRequestManagement.post( + '/Actions/StartPostgreSQLExplain', + body, + ); + }, }; From 858c2d5d94fb3ac2ad5360fed9e46c8d3d942635 Mon Sep 17 00:00:00 2001 From: Matej Kubinec Date: Thu, 2 Mar 2023 10:33:33 +0100 Subject: [PATCH 2/3] PMM-10893 Show either example or fingerprint --- .../components/Details/Example/Example.tools.tsx | 4 ++++ .../panel/components/Details/Example/Example.tsx | 12 ++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tools.tsx b/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tools.tsx index 6635aea221..19c4962d69 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tools.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tools.tsx @@ -4,6 +4,7 @@ import { ReactJSON } from 'shared/components/Elements/ReactJSON/ReactJSON'; import { Databases, logger } from 'shared/core'; import { Highlight } from 'shared/components/Hightlight/Highlight'; import ParseError from './ParseError/ParseError'; +import { QueryExampleResponseItem } from '../Details.types'; export const getExample = (databaseType) => (example: any): any => { if (databaseType === Databases.mongodb) { @@ -22,3 +23,6 @@ export const getExample = (databaseType) => (example: any): any => { ); }; + +export const extractExample = (example: QueryExampleResponseItem) => example.example +|| example.explain_fingerprint; diff --git a/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tsx b/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tsx index 03470167ad..7c8ee6c74b 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/Example/Example.tsx @@ -1,21 +1,17 @@ import React, { FC } from 'react'; import { Overlay } from 'shared/components/Elements/Overlay/Overlay'; -import { getExample } from './Example.tools'; +import { extractExample, getExample } from './Example.tools'; import { ExampleInterface } from './Example.types'; import { Messages } from '../Details.messages'; import { OVERLAY_LOADER_SIZE } from '../Details.constants'; const Example: FC = ({ databaseType, examples, loading }) => { - const isExample = examples && examples.filter((example) => example.example).length; + const isExample = examples && examples.filter(extractExample).length; + const examplesList = examples.map(extractExample).filter(Boolean).map(getExample(databaseType)); return ( - {isExample && !loading - ? examples - .filter(({ example }) => example) - .map((example) => example.example) - .map(getExample(databaseType)) - : null} + {isExample && !loading ? examplesList : null} {!isExample ?
{Messages.noExamplesFound}
: null}
); From 59d8bef96da95d5f843090ada6f2faa47db24226 Mon Sep 17 00:00:00 2001 From: Matej Kubinec Date: Thu, 2 Mar 2023 14:23:37 +0100 Subject: [PATCH 3/3] PMM-10893 Correctly handle available example --- .../components/Details/Explain/Explain.tools.ts | 8 ++++---- .../ExplainPlaceholders/ExplainPlaceholders.tsx | 2 +- .../Details/database-models/mysql/mysql.ts | 12 ++++++++---- .../Details/database-models/postgresql/postgresql.ts | 10 ++++++---- .../database-models/postgresql/postgresql.types.ts | 4 ++-- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts b/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts index dc0d6d5d62..fd55df76c3 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/Explain/Explain.tools.ts @@ -71,11 +71,11 @@ export const fetchExplains = async ( try { const hasPlaceholders = placeholders || !example.placeholders_count; - if (databaseType === Databases.postgresql && hasPlaceholders) { + if (databaseType === Databases.postgresql && (hasPlaceholders || !!example.example)) { const payload = { serviceId: example.service_id, queryId, - placeholders: placeholders || [], + values: placeholders || [], }; const explain = await postgresqlMethods.getExplain(payload).then(getActionResult); @@ -89,11 +89,11 @@ export const fetchExplains = async ( }; } - if (databaseType === Databases.mysql && hasPlaceholders) { + if (databaseType === Databases.mysql && (hasPlaceholders || !!example.example)) { const payload = { example, queryId, - placeholders, + values: placeholders, }; const [classicResult, jsonResult] = await Promise.all([ diff --git a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx index 8fca1536a6..bc69928ce6 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx +++ b/pmm-app/src/pmm-qan/panel/components/Details/ExplainPlaceholders/ExplainPlaceholders.tsx @@ -29,7 +29,7 @@ const ExplainPlaceholders: React.FC = ({ setJsonExplain(actionResult); setVisualExplain(actionResult); - if (example && !example.placeholders_count) { + if (example && (!example.placeholders_count || example.example)) { setInitialized(true); handlePlaceholderSubmit({ placeholders: [] }); } else if (!example) { diff --git a/pmm-app/src/pmm-qan/panel/components/Details/database-models/mysql/mysql.ts b/pmm-app/src/pmm-qan/panel/components/Details/database-models/mysql/mysql.ts index 4f8ac8433a..059a998726 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/database-models/mysql/mysql.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/database-models/mysql/mysql.ts @@ -43,9 +43,11 @@ export const mysqlMethods = { return result.action_id; }, - getExplainJSON: async ({ example, queryId, placeholders }) => { + getExplainJSON: async ({ example, queryId, values }) => { try { - const payload = { query_id: queryId, placeholders: placeholders || [] }; + const payload = example.example + ? { query: example.example } + : { query_id: queryId, values: values || [] }; const result = await MysqlDatabaseService.getTraditionalExplainJSONMysql({ database: example.schema, @@ -61,9 +63,11 @@ export const mysqlMethods = { } }, - getExplainTraditional: async ({ example, queryId, placeholders }) => { + getExplainTraditional: async ({ example, queryId, values }) => { try { - const payload = placeholders?.length ? { query_id: queryId, placeholders } : { query_id: queryId }; + const payload = example.example + ? { query: example.example } + : { query_id: queryId, values: values || [] }; const result = await MysqlDatabaseService.getTraditionalExplainMysql({ database: example.schema, diff --git a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts index 2a57ed3378..15caf13ff8 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.ts @@ -2,12 +2,14 @@ import { PostgreSQLExplain } from './postgresql.types'; import PostgresqlDatabaseService from './service'; export const postgresqlMethods = { - getExplain: async ({ placeholders, queryId, serviceId }: PostgreSQLExplain): Promise => { - const result = await PostgresqlDatabaseService.getPostgreSQLExplain({ + getExplain: async ({ values, queryId, serviceId }: PostgreSQLExplain): Promise => { + const payload = { queryId, serviceId, - placeholders, - }); + values, + }; + + const result = await PostgresqlDatabaseService.getPostgreSQLExplain(payload); return result.action_id; }, diff --git a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts index 0f5a5305e3..309b7b36ab 100644 --- a/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts +++ b/pmm-app/src/pmm-qan/panel/components/Details/database-models/postgresql/postgresql.types.ts @@ -2,7 +2,7 @@ export interface PostgreSQLExplainBody { pmmAgentId?: string; serviceId: string; queryId: string; - placeholders: string[]; + values: string[]; database?: string; } @@ -14,5 +14,5 @@ export interface PostgreSQLExplainResponse { export interface PostgreSQLExplain { serviceId: string; queryId: string; - placeholders: string[]; + values: string[]; }