Skip to content

Commit

Permalink
Merge #75097 #75490
Browse files Browse the repository at this point in the history
75097: ui: allow stmts page to search across explain plan page r=gtr a=gtr

Closes #71615.
    
Previously, the search functionality for the stmts page only allowed a search
through the statement query. This change adds the statement's Plan as part of
that search.

Release note (ui change): logical plan text included in searchable text for
stmts page.

Demo video: shows that the search feature works for statements' plan

https://user-images.githubusercontent.com/35943354/150594026-ba6325b1-90f1-4830-9b88-c021d4781596.mov

75490: ui: switch order of tabs on SQL Activity r=maryliag a=maryliag

Previously, the tabs under SQL Activity where
Sessions, Transactions and Statements. This commit changes
the order to be Statements, Transactions and Sessions.

Fixes #74644

Release note (ui change): Change the order of tabs under SQL
Activity page to be Statements, Transactions and Sessions.

Co-authored-by: Gerardo Torres <[email protected]>
Co-authored-by: Marylia Gutierrez <[email protected]>
  • Loading branch information
3 people committed Jan 25, 2022
3 parents 507dd71 + 78443e6 + b4908da commit 0e932c3
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
flattenTreeAttributes,
flattenAttributes,
standardizeKey,
planNodeToString,
planNodeAttrsToString,
} from "./planView";
import IAttr = cockroach.sql.ExplainTreePlanNode.IAttr;

Expand Down Expand Up @@ -260,4 +262,94 @@ describe("planView", () => {
assert.equal(standardizeKey("(anti) hello world"), "helloWorld");
});
});

describe("planNodeAttrsToString", () => {
it("should convert an array of FlatPlanNodeAttribute[] into a string", () => {
const testNodeAttrs: FlatPlanNodeAttribute[] = [
{
key: "Into",
values: ["users(id, city, name, address, credit_card)"],
warn: false,
},
{
key: "Size",
values: ["5 columns, 3 rows"],
warn: false,
},
];

const expectedString =
"Into users(id, city, name, address, credit_card) Size 5 columns, 3 rows";

assert.equal(planNodeAttrsToString(testNodeAttrs), expectedString);
});
});

describe("planNodeToString", () => {
it("should recursively convert a FlatPlanNode into a string.", () => {
const testPlanNode: FlatPlanNode = {
name: "insert fast path",
attrs: [
{
key: "Into",
values: ["users(id, city, name, address, credit_card)"],
warn: false,
},
{
key: "Size",
values: ["5 columns, 3 rows"],
warn: false,
},
],
children: [],
};

const expectedString =
"insert fast path Into users(id, city, name, address, credit_card) Size 5 columns, 3 rows";

assert.equal(planNodeToString(testPlanNode), expectedString);
});

it("should recursively convert a FlatPlanNode (with children) into a string.", () => {
const testPlanNode: FlatPlanNode = {
name: "render",
attrs: [],
children: [
{
name: "group (scalar)",
attrs: [],
children: [
{
name: "filter",
attrs: [
{
key: "filter",
values: ["variable = _"],
warn: false,
},
],
children: [
{
name: "virtual table",
attrs: [
{
key: "table",
values: ["cluster_settings@primary"],
warn: false,
},
],
children: [],
},
],
},
],
},
],
};

const expectedString =
"render group (scalar) filter filter variable = _ virtual table table cluster_settings@primary";
assert.equal(planNodeToString(testPlanNode), expectedString);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@ function warnForAttribute(attr: IAttr): boolean {
return false;
}

// planNodeAttrsToString converts an array of FlatPlanNodeAttribute[] into a string.
export function planNodeAttrsToString(attrs: FlatPlanNodeAttribute[]): string {
return attrs.map(attr => `${attr.key} ${attr.values.join(" ")}`).join(" ");
}

// planNodeToString recursively converts a FlatPlanNode into a string.
export function planNodeToString(plan: FlatPlanNode): string {
const str = `${plan.name} ${planNodeAttrsToString(plan.attrs)}`;

if (plan.children.length > 0) {
return `${str} ${plan.children
.map(child => planNodeToString(child))
.join(" ")}`;
}

return str;
}

// flattenAttributes takes a list of attrs (IAttr[]) and collapses
// all the values for the same key (FlatPlanNodeAttribute). For example,
// if attrs was:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ import { ReactWrapper, mount } from "enzyme";
import { MemoryRouter } from "react-router-dom";

import {
filterBySearchQuery,
StatementsPage,
StatementsPageProps,
StatementsPageState,
} from "src/statementsPage";
import statementsPagePropsFixture from "./statementsPage.fixture";
import { AggregateStatistics } from "../statementsTable";
import { FlatPlanNode } from "../statementDetails";

describe("StatementsPage", () => {
describe("Statements table", () => {
Expand All @@ -43,4 +46,65 @@ describe("StatementsPage", () => {
assert.equal(statementsPageInstance.props.sortSetting.ascending, false);
});
});

describe("filterBySearchQuery", () => {
const testPlanNode: FlatPlanNode = {
name: "render",
attrs: [],
children: [
{
name: "group (scalar)",
attrs: [],
children: [
{
name: "filter",
attrs: [
{
key: "filter",
values: ["variable = _"],
warn: false,
},
],
children: [
{
name: "virtual table",
attrs: [
{
key: "table",
values: ["cluster_settings@primary"],
warn: false,
},
],
children: [],
},
],
},
],
},
],
};

const statement: AggregateStatistics = {
aggregatedFingerprintID: "",
aggregatedTs: 0,
aggregationInterval: 0,
database: "",
fullScan: false,
implicitTxn: false,
summary: "",
label:
"SELECT count(*) > _ FROM [SHOW ALL CLUSTER SETTINGS] AS _ (v) WHERE v = '_'",
stats: {
sensitive_info: {
most_recent_plan_description: testPlanNode,
},
},
};

assert.equal(filterBySearchQuery(statement, "select"), true);
assert.equal(filterBySearchQuery(statement, "virtual table"), true);
assert.equal(filterBySearchQuery(statement, "group (scalar)"), true);
assert.equal(filterBySearchQuery(statement, "node_build_info"), false);
assert.equal(filterBySearchQuery(statement, "crdb_internal"), false);
});
});
32 changes: 23 additions & 9 deletions pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import {
} from "../timeScaleDropdown";

import { commonStyles } from "../common";
import { flattenTreeAttributes, planNodeToString } from "../statementDetails";
const cx = classNames.bind(styles);
const sortableTableCx = classNames.bind(sortableTableStyles);

Expand Down Expand Up @@ -146,6 +147,25 @@ function statementsRequestFromProps(
});
}

// filterBySearchQuery returns true if a search query matches the statement.
export function filterBySearchQuery(
statement: AggregateStatistics,
search: string,
): boolean {
const label = statement.label;
const plan = planNodeToString(
flattenTreeAttributes(
statement.stats.sensitive_info &&
statement.stats.sensitive_info.most_recent_plan_description,
),
);
const matchString = `${label} ${plan}`.toLowerCase();
return search
.toLowerCase()
.split(" ")
.every(val => matchString.includes(val));
}

export class StatementsPage extends React.Component<
StatementsPageProps,
StatementsPageState
Expand Down Expand Up @@ -408,15 +428,6 @@ export class StatementsPage extends React.Component<
databases.length == 0 || databases.includes(statement.database),
)
.filter(statement => (filters.fullScan ? statement.fullScan : true))
.filter(statement =>
search
? search
.split(" ")
.every(val =>
statement.label.toLowerCase().includes(val.toLowerCase()),
)
: true,
)
.filter(
statement =>
statement.stats.service_lat.mean >= timeValue ||
Expand Down Expand Up @@ -456,6 +467,9 @@ export class StatementsPage extends React.Component<
statement.stats.nodes.map(node => "n" + node),
nodes,
)),
)
.filter(statement =>
search ? filterBySearchQuery(statement, search) : true,
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { RouteComponentProps } from "react-router-dom";
const { TabPane } = Tabs;

const SQLActivityPage = (props: RouteComponentProps) => {
const defaultTab = util.queryByName(props.location, "tab") || "Sessions";
const defaultTab = util.queryByName(props.location, "tab") || "Statements";
const [currentTab, setCurrentTab] = useState(defaultTab);

const onTabChange = (tabId: string): void => {
Expand All @@ -33,7 +33,7 @@ const SQLActivityPage = (props: RouteComponentProps) => {
};

useEffect(() => {
const queryTab = util.queryByName(props.location, "tab") || "Sessions";
const queryTab = util.queryByName(props.location, "tab") || "Statements";
if (queryTab !== currentTab) {
setCurrentTab(queryTab);
}
Expand All @@ -49,14 +49,14 @@ const SQLActivityPage = (props: RouteComponentProps) => {
onChange={onTabChange}
activeKey={currentTab}
>
<TabPane tab="Sessions" key="Sessions">
<SessionsPageConnected />
<TabPane tab="Statements" key="Statements">
<StatementsPageConnected />
</TabPane>
<TabPane tab="Transactions" key="Transactions">
<TransactionsPageConnected />
</TabPane>
<TabPane tab="Statements" key="Statements">
<StatementsPageConnected />
<TabPane tab="Sessions" key="Sessions">
<SessionsPageConnected />
</TabPane>
</Tabs>
</div>
Expand Down

0 comments on commit 0e932c3

Please sign in to comment.