diff --git a/pkg/server/combined_statement_stats.go b/pkg/server/combined_statement_stats.go
index 18d65a9d633f..423825157766 100644
--- a/pkg/server/combined_statement_stats.go
+++ b/pkg/server/combined_statement_stats.go
@@ -21,7 +21,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/settings/cluster"
"github.com/cockroachdb/cockroach/pkg/sql"
"github.com/cockroachdb/cockroach/pkg/sql/appstatspb"
- "github.com/cockroachdb/cockroach/pkg/sql/parser"
"github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
@@ -732,15 +731,7 @@ func getTotalStatementDetails(
return statement, serverError(ctx, err)
}
- queryTree, err := parser.ParseOne(aggregatedMetadata.Query)
- if err != nil {
- return statement, serverError(ctx, err)
- }
- cfg := tree.DefaultPrettyCfg()
- cfg.Align = tree.PrettyAlignOnly
- cfg.LineWidth = tree.ConsoleLineWidth
- aggregatedMetadata.FormattedQuery = cfg.Pretty(queryTree.AST)
-
+ aggregatedMetadata.FormattedQuery = aggregatedMetadata.Query
aggregatedMetadata.FingerprintID = string(tree.MustBeDString(row[3]))
statement = serverpb.StatementDetailsResponse_CollectedStatementSummary{
diff --git a/pkg/sql/appstatspb/app_stats.proto b/pkg/sql/appstatspb/app_stats.proto
index 0e57a4a9584d..3361c6a9fc72 100644
--- a/pkg/sql/appstatspb/app_stats.proto
+++ b/pkg/sql/appstatspb/app_stats.proto
@@ -226,9 +226,8 @@ message StatementStatisticsKey {
message AggregatedStatementMetadata {
optional string query = 1 [(gogoproto.nullable) = false];
- // Formatted query is the return of the key_data.query after prettify_statement.
- // The query above cannot be replaced by the formatted value, because is used as is for
- // diagnostic bundle.
+ // Formatted query is the same value of query. It used to be formatted with prettify_statement,
+ // but until that function is improved (#91197), it should not be used.
optional string formatted_query = 2 [(gogoproto.nullable) = false];
optional string query_summary = 3 [(gogoproto.nullable) = false];
optional string stmt_type = 4 [(gogoproto.nullable) = false];
diff --git a/pkg/ui/workspaces/cluster-ui/src/api/txnInsightsApi.ts b/pkg/ui/workspaces/cluster-ui/src/api/txnInsightsApi.ts
index 46ca3adecb3e..1e7b99a3c564 100644
--- a/pkg/ui/workspaces/cluster-ui/src/api/txnInsightsApi.ts
+++ b/pkg/ui/workspaces/cluster-ui/src/api/txnInsightsApi.ts
@@ -110,7 +110,7 @@ type FingerprintStmtsResponseColumns = {
const fingerprintStmtsQuery = (stmtFingerprintIDs: string[]): string => `
SELECT
DISTINCT ON (fingerprint_id) encode(fingerprint_id, 'hex') AS statement_fingerprint_id,
- prettify_statement(metadata ->> 'query', 108, 1, 1) AS query
+ (metadata ->> 'query') AS query
FROM crdb_internal.statement_statistics
WHERE encode(fingerprint_id, 'hex') =
ANY ARRAY[ ${stmtFingerprintIDs.map(id => `'${id}'`).join(",")} ]`;
diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx
index 1e656f90b081..a90ff2251115 100644
--- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx
@@ -159,7 +159,11 @@ export const StatementInsightDetails: React.FC<
diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsOverviewTab.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsOverviewTab.tsx
index 9b15ee954e7b..cb74b65ecbd3 100644
--- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsOverviewTab.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsOverviewTab.tsx
@@ -131,7 +131,11 @@ the maximum number of statements was reached in the console.`;
>
-
+
{txnDetails && (
diff --git a/pkg/ui/workspaces/cluster-ui/src/jobs/jobDetailsPage/jobDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/jobs/jobDetailsPage/jobDetails.tsx
index 9d827502dabc..72507998bb0f 100644
--- a/pkg/ui/workspaces/cluster-ui/src/jobs/jobDetailsPage/jobDetails.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/jobs/jobDetailsPage/jobDetails.tsx
@@ -99,7 +99,11 @@ export class JobDetails extends React.Component {
<>
-
+
diff --git a/pkg/ui/workspaces/cluster-ui/src/sql/box.tsx b/pkg/ui/workspaces/cluster-ui/src/sql/box.tsx
index 511f23f00ddf..10a923e84a1a 100644
--- a/pkg/ui/workspaces/cluster-ui/src/sql/box.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/sql/box.tsx
@@ -14,6 +14,7 @@ import classNames from "classnames/bind";
import styles from "./sqlhighlight.module.scss";
import { api as clusterUiApi } from "../index";
+import { FormatQuery } from "src/util";
export enum SqlBoxSize {
small = "small",
@@ -26,6 +27,7 @@ export interface SqlBoxProps {
zone?: clusterUiApi.DatabaseDetailsResponse;
className?: string;
size?: SqlBoxSize;
+ format?: boolean;
}
const cx = classNames.bind(styles);
@@ -33,10 +35,13 @@ const cx = classNames.bind(styles);
export class SqlBox extends React.Component {
preNode: React.RefObject = React.createRef();
render(): React.ReactElement {
+ const value = this.props.format
+ ? FormatQuery(this.props.value)
+ : this.props.value;
const sizeClass = this.props.size ? this.props.size : "";
return (
-
+
);
}
diff --git a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx
index d4a27b9b7ee6..303acbac3143 100644
--- a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx
@@ -501,6 +501,7 @@ export class StatementDetails extends React.Component<
@@ -684,6 +685,7 @@ export class StatementDetails extends React.Component<
@@ -845,7 +847,11 @@ export class StatementDetails extends React.Component<
-
+
diff --git a/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx
index a5d5d23b0564..63eb25d3b9be 100644
--- a/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx
@@ -338,6 +338,7 @@ export class TransactionDetails extends React.Component<
@@ -458,6 +459,7 @@ export class TransactionDetails extends React.Component<
diff --git a/pkg/ui/workspaces/cluster-ui/src/util/format.ts b/pkg/ui/workspaces/cluster-ui/src/util/format.ts
index 8fcb4ec1d52c..a9c67ca6161f 100644
--- a/pkg/ui/workspaces/cluster-ui/src/util/format.ts
+++ b/pkg/ui/workspaces/cluster-ui/src/util/format.ts
@@ -352,3 +352,51 @@ export function EncodeDatabaseTableIndexUri(
export function EncodeDatabaseUri(db: string): string {
return `/database/${EncodeUriName(db)}`;
}
+
+interface BreakLineReplacement {
+ [key: string]: string;
+}
+
+const breakLinesKeywords: BreakLineReplacement = {
+ " FROM ": " FROM ",
+ " WHERE ": " WHERE ",
+ " AND ": " AND ",
+ " ORDER ": " ORDER ",
+ " LIMIT ": " LIMIT ",
+ " JOIN ": " JOIN ",
+ " ON ": " ON ",
+ " VALUES ": " VALUES ",
+};
+const LINE_BREAK_LIMIT = 100;
+
+export function FormatQuery(query: string): string {
+ if (query == null) {
+ return "";
+ }
+ Object.keys(breakLinesKeywords).forEach(key => {
+ query = query.replace(new RegExp(key, "g"), `\n${breakLinesKeywords[key]}`);
+ });
+ const lines = query.split("\n").map(line => {
+ if (line.length <= LINE_BREAK_LIMIT) {
+ return line;
+ }
+ return breakLongLine(line, LINE_BREAK_LIMIT);
+ });
+
+ return lines.join("\n");
+}
+
+function breakLongLine(line: string, limit: number): string {
+ if (line.length <= limit) {
+ return line;
+ }
+ const idxComma = line.indexOf(",", limit);
+ if (idxComma == -1) {
+ return line;
+ }
+
+ return `${line.substring(0, idxComma + 1)}\n${breakLongLine(
+ line.substring(idxComma + 1).trim(),
+ limit,
+ )}`;
+}