Revert "reset states fixes (#2207)"

This reverts commit a3a2bf2e3a.
This commit is contained in:
nishthaAhujaa
2025-10-16 00:19:09 +05:30
parent a3a2bf2e3a
commit 163d25dfd9
4 changed files with 82 additions and 136 deletions

View File

@@ -13,85 +13,80 @@ interface IndexObject {
path?: string; path?: string;
} }
// SDK response format export interface IndexMetricsJson {
export interface IndexMetricsResponse { included?: IIndexMetric[];
UtilizedIndexes?: { notIncluded?: IIndexMetric[];
SingleIndexes?: Array<{ IndexSpec: string; IndexImpactScore?: string }>;
CompositeIndexes?: Array<{ IndexSpecs: string[]; IndexImpactScore?: string }>;
};
PotentialIndexes?: {
SingleIndexes?: Array<{ IndexSpec: string; IndexImpactScore?: string }>;
CompositeIndexes?: Array<{ IndexSpecs: string[]; IndexImpactScore?: string }>;
};
} }
export function parseIndexMetrics(indexMetrics: string | IndexMetricsJson): {
export function parseIndexMetrics(indexMetrics: IndexMetricsResponse): {
included: IIndexMetric[]; included: IIndexMetric[];
notIncluded: IIndexMetric[]; notIncluded: IIndexMetric[];
} { } {
// If already JSON, just extract arrays
if (typeof indexMetrics === "object" && indexMetrics !== null) {
return {
included: Array.isArray(indexMetrics.included) ? indexMetrics.included : [],
notIncluded: Array.isArray(indexMetrics.notIncluded) ? indexMetrics.notIncluded : [],
};
}
// Otherwise, parse as string (current SDK)
const included: IIndexMetric[] = []; const included: IIndexMetric[] = [];
const notIncluded: IIndexMetric[] = []; const notIncluded: IIndexMetric[] = [];
const lines = (indexMetrics as string)
.split("\n")
.map((line) => line.trim())
.filter(Boolean);
let currentSection = "";
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.startsWith("Utilized Single Indexes") || line.startsWith("Utilized Composite Indexes")) {
currentSection = "included";
} else if (line.startsWith("Potential Single Indexes") || line.startsWith("Potential Composite Indexes")) {
currentSection = "notIncluded";
} else if (line.startsWith("Index Spec:")) {
const index = line.replace("Index Spec:", "").trim();
const impactLine = lines[i + 1];
const impact = impactLine?.includes("Index Impact Score:") ? impactLine.split(":")[1].trim() : "Unknown";
// Process UtilizedIndexes (Included) const isComposite = index.includes(",");
if (indexMetrics.UtilizedIndexes) {
// Single indexes
indexMetrics.UtilizedIndexes.SingleIndexes?.forEach((index) => {
included.push({
index: index.IndexSpec,
impact: index.IndexImpactScore || "Utilized",
section: "Included",
path: index.IndexSpec,
});
});
// Composite indexes const sectionMap: Record<string, "Included" | "Not Included"> = {
indexMetrics.UtilizedIndexes.CompositeIndexes?.forEach((index) => { included: "Included",
const compositeSpec = index.IndexSpecs.join(", "); notIncluded: "Not Included",
included.push({ };
index: compositeSpec,
impact: index.IndexImpactScore || "Utilized", const indexObj: IndexObject = { index, impact, section: sectionMap[currentSection] ?? "Header" };
section: "Included", if (isComposite) {
composite: index.IndexSpecs.map((spec) => { indexObj.composite = index.split(",").map((part: string) => {
const [path, order] = spec.trim().split(/\s+/); const [path, order] = part.trim().split(/\s+/);
return { return {
path: path.trim(), path: path.trim(),
order: order?.toLowerCase() === "desc" ? "descending" : "ascending", order: order?.toLowerCase() === "desc" ? "descending" : "ascending",
}; };
}),
});
}); });
} else {
let path = "/unknown/*";
const pathRegex = /\/[^/\s*?]+(?:\/[^/\s*?]+)*(\/\*|\?)/;
const match = index.match(pathRegex);
if (match) {
path = match[0];
} else {
const simplePathRegex = /\/[^/\s]+/;
const simpleMatch = index.match(simplePathRegex);
if (simpleMatch) {
path = simpleMatch[0] + "/*";
}
}
indexObj.path = path;
} }
// Process PotentialIndexes (Not Included) if (currentSection === "included") {
if (indexMetrics.PotentialIndexes) { included.push(indexObj);
// Single indexes } else if (currentSection === "notIncluded") {
indexMetrics.PotentialIndexes.SingleIndexes?.forEach((index) => { notIncluded.push(indexObj);
notIncluded.push({ }
index: index.IndexSpec, }
impact: index.IndexImpactScore || "Unknown",
section: "Not Included",
path: index.IndexSpec,
});
});
// Composite indexes
indexMetrics.PotentialIndexes.CompositeIndexes?.forEach((index) => {
const compositeSpec = index.IndexSpecs.join(", ");
notIncluded.push({
index: compositeSpec,
impact: index.IndexImpactScore || "Unknown",
section: "Not Included",
composite: index.IndexSpecs.map((spec) => {
const [path, order] = spec.trim().split(/\s+/);
return {
path: path.trim(),
order: order?.toLowerCase() === "desc" ? "descending" : "ascending",
};
}),
});
});
} }
return { included, notIncluded }; return { included, notIncluded };
} }

View File

@@ -3,21 +3,18 @@ import QueryError from "Common/QueryError";
import { IndeterminateProgressBar } from "Explorer/Controls/IndeterminateProgressBar"; import { IndeterminateProgressBar } from "Explorer/Controls/IndeterminateProgressBar";
import { MessageBanner } from "Explorer/Controls/MessageBanner"; import { MessageBanner } from "Explorer/Controls/MessageBanner";
import { useQueryTabStyles } from "Explorer/Tabs/QueryTab/Styles"; import { useQueryTabStyles } from "Explorer/Tabs/QueryTab/Styles";
import useZoomLevel from "hooks/useZoomLevel";
import React from "react"; import React from "react";
import { conditionalClass } from "Utils/StyleUtils";
import RunQuery from "../../../../images/RunQuery.png"; import RunQuery from "../../../../images/RunQuery.png";
import { QueryResults } from "../../../Contracts/ViewModels"; import { QueryResults } from "../../../Contracts/ViewModels";
import { ErrorList } from "./ErrorList"; import { ErrorList } from "./ErrorList";
import { ResultsView } from "./ResultsView"; import { ResultsView } from "./ResultsView";
import useZoomLevel from "hooks/useZoomLevel";
import { conditionalClass } from "Utils/StyleUtils";
export interface ResultsViewProps { export interface ResultsViewProps {
isMongoDB: boolean; isMongoDB: boolean;
queryResults: QueryResults; queryResults: QueryResults;
executeQueryDocumentsPage: (firstItemIndex: number) => Promise<void>; executeQueryDocumentsPage: (firstItemIndex: number) => Promise<void>;
queryText?: string;
databaseId?: string;
containerId?: string;
} }
interface QueryResultProps extends ResultsViewProps { interface QueryResultProps extends ResultsViewProps {
@@ -52,9 +49,6 @@ export const QueryResultSection: React.FC<QueryResultProps> = ({
queryResults, queryResults,
executeQueryDocumentsPage, executeQueryDocumentsPage,
isExecuting, isExecuting,
queryText,
databaseId,
containerId,
}: QueryResultProps): JSX.Element => { }: QueryResultProps): JSX.Element => {
const styles = useQueryTabStyles(); const styles = useQueryTabStyles();
const maybeSubQuery = queryEditorContent && /.*\(.*SELECT.*\)/i.test(queryEditorContent); const maybeSubQuery = queryEditorContent && /.*\(.*SELECT.*\)/i.test(queryEditorContent);
@@ -97,9 +91,6 @@ export const QueryResultSection: React.FC<QueryResultProps> = ({
queryResults={queryResults} queryResults={queryResults}
executeQueryDocumentsPage={executeQueryDocumentsPage} executeQueryDocumentsPage={executeQueryDocumentsPage}
isMongoDB={isMongoDB} isMongoDB={isMongoDB}
queryText={queryText || queryEditorContent}
databaseId={databaseId}
containerId={containerId}
/> />
) : ( ) : (
<ExecuteQueryCallToAction /> <ExecuteQueryCallToAction />

View File

@@ -798,8 +798,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
this.props.copilotStore, this.props.copilotStore,
) )
} }
databaseId={this.props.collection.databaseId}
containerId={this.props.collection.id()}
/> />
) : ( ) : (
<QueryResultSection <QueryResultSection
@@ -811,8 +809,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
executeQueryDocumentsPage={(firstItemIndex: number) => executeQueryDocumentsPage={(firstItemIndex: number) =>
this._executeQueryDocumentsPage(firstItemIndex) this._executeQueryDocumentsPage(firstItemIndex)
} }
databaseId={this.props.collection.databaseId}
containerId={this.props.collection.id()}
/> />
)} )}
</Allotment.Pane> </Allotment.Pane>

View File

@@ -28,7 +28,8 @@ import { HttpHeaders } from "Common/Constants";
import MongoUtility from "Common/MongoUtility"; import MongoUtility from "Common/MongoUtility";
import { QueryMetrics } from "Contracts/DataModels"; import { QueryMetrics } from "Contracts/DataModels";
import { EditorReact } from "Explorer/Controls/Editor/EditorReact"; import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
import { IDocument } from "Explorer/Tabs/QueryTab/QueryTabComponent"; import { parseIndexMetrics, renderImpactDots } from "Explorer/Tabs/QueryTab/IndexAdvisorUtils";
import { IDocument, useQueryMetadataStore } from "Explorer/Tabs/QueryTab/QueryTabComponent";
import { useQueryTabStyles } from "Explorer/Tabs/QueryTab/Styles"; import { useQueryTabStyles } from "Explorer/Tabs/QueryTab/Styles";
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { userContext } from "UserContext"; import { userContext } from "UserContext";
@@ -36,7 +37,6 @@ import { logConsoleProgress } from "Utils/NotificationConsoleUtils";
import create from "zustand"; import create from "zustand";
import { client } from "../../../Common/CosmosClient"; import { client } from "../../../Common/CosmosClient";
import { handleError } from "../../../Common/ErrorHandlingUtils"; import { handleError } from "../../../Common/ErrorHandlingUtils";
import { parseIndexMetrics, renderImpactDots, type IndexMetricsResponse } from "./IndexAdvisorUtils";
import { ResultsViewProps } from "./QueryResultSection"; import { ResultsViewProps } from "./QueryResultSection";
import { useIndexAdvisorStyles } from "./StylesAdvisor"; import { useIndexAdvisorStyles } from "./StylesAdvisor";
enum ResultsTabs { enum ResultsTabs {
@@ -394,7 +394,8 @@ const QueryStatsTab: React.FC<Pick<ResultsViewProps, "queryResults">> = ({ query
}, },
{ {
metric: "User defined function execution time", metric: "User defined function execution time",
value: `${aggregatedQueryMetrics.runtimeExecutionTimes?.userDefinedFunctionExecutionTime?.toString() || 0 value: `${
aggregatedQueryMetrics.runtimeExecutionTimes?.userDefinedFunctionExecutionTime?.toString() || 0
} ms`, } ms`,
toolTip: "Total time spent executing user-defined functions", toolTip: "Total time spent executing user-defined functions",
}, },
@@ -543,14 +544,11 @@ export interface IIndexMetric {
path?: string; path?: string;
composite?: { path: string; order: string }[]; composite?: { path: string; order: string }[];
} }
export const IndexAdvisorTab: React.FC<{ export const IndexAdvisorTab: React.FC = () => {
queryText?: string;
databaseId?: string;
containerId?: string;
}> = ({ queryText, databaseId, containerId }) => {
const style = useIndexAdvisorStyles(); const style = useIndexAdvisorStyles();
const { userQuery, databaseId, containerId } = useQueryMetadataStore();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [indexMetrics, setIndexMetrics] = useState<IndexMetricsResponse | null>(null); const [indexMetrics, setIndexMetrics] = useState<string | null>(null);
const [showIncluded, setShowIncluded] = useState(true); const [showIncluded, setShowIncluded] = useState(true);
const [showNotIncluded, setShowNotIncluded] = useState(true); const [showNotIncluded, setShowNotIncluded] = useState(true);
const [selectedIndexes, setSelectedIndexes] = useState<IIndexMetric[]>([]); const [selectedIndexes, setSelectedIndexes] = useState<IIndexMetric[]>([]);
@@ -564,26 +562,10 @@ export const IndexAdvisorTab: React.FC<{
useEffect(() => { useEffect(() => {
const fetchIndexMetrics = async () => { const fetchIndexMetrics = async () => {
// Reset all states when query parameters change
setLoading(true);
setIndexMetrics(null);
setIncludedIndexes([]);
setNotIncludedIndexes([]);
setSelectedIndexes([]);
setSelectAll(false);
setUpdateMessageShown(false);
setIsUpdating(false);
setJustUpdatedPolicy(false);
if (!queryText || !databaseId || !containerId) {
setLoading(false);
return;
}
const clearMessage = logConsoleProgress(`Querying items with IndexMetrics in container ${containerId}`); const clearMessage = logConsoleProgress(`Querying items with IndexMetrics in container ${containerId}`);
try { try {
const querySpec = { const querySpec = {
query: queryText, query: userQuery,
}; };
const sdkResponse = await client() const sdkResponse = await client()
.database(databaseId) .database(databaseId)
@@ -592,12 +574,7 @@ export const IndexAdvisorTab: React.FC<{
populateIndexMetrics: true, populateIndexMetrics: true,
}) })
.fetchAll(); .fetchAll();
setIndexMetrics(sdkResponse.indexMetrics);
const parsedIndexMetrics = typeof sdkResponse.indexMetrics === 'string'
? JSON.parse(sdkResponse.indexMetrics)
: sdkResponse.indexMetrics;
setIndexMetrics(parsedIndexMetrics);
} catch (error) { } catch (error) {
handleError(error, "queryItemsWithIndexMetrics", `Error querying items from ${containerId}`); handleError(error, "queryItemsWithIndexMetrics", `Error querying items from ${containerId}`);
} finally { } finally {
@@ -605,9 +582,10 @@ export const IndexAdvisorTab: React.FC<{
setLoading(false); setLoading(false);
} }
}; };
if (userQuery && databaseId && containerId) {
fetchIndexMetrics(); fetchIndexMetrics();
}, [queryText, databaseId, containerId]); }
}, [userQuery, databaseId, containerId]);
useEffect(() => { useEffect(() => {
if (!indexMetrics) { if (!indexMetrics) {
@@ -850,21 +828,13 @@ export const IndexAdvisorTab: React.FC<{
</div> </div>
); );
}; };
export const ResultsView: React.FC<ResultsViewProps> = ({ export const ResultsView: React.FC<ResultsViewProps> = ({ isMongoDB, queryResults, executeQueryDocumentsPage }) => {
isMongoDB,
queryResults,
executeQueryDocumentsPage,
queryText,
databaseId,
containerId
}) => {
const styles = useQueryTabStyles(); const styles = useQueryTabStyles();
const [activeTab, setActiveTab] = useState<ResultsTabs>(ResultsTabs.Results); const [activeTab, setActiveTab] = useState<ResultsTabs>(ResultsTabs.Results);
const onTabSelect = useCallback((event: SelectTabEvent, data: SelectTabData) => { const onTabSelect = useCallback((event: SelectTabEvent, data: SelectTabData) => {
setActiveTab(data.value as ResultsTabs); setActiveTab(data.value as ResultsTabs);
}, []); }, []);
return ( return (
<div data-test="QueryTab/ResultsPane/ResultsView" className={styles.queryResultsTabPanel}> <div data-test="QueryTab/ResultsPane/ResultsView" className={styles.queryResultsTabPanel}>
<TabList selectedValue={activeTab} onTabSelect={onTabSelect}> <TabList selectedValue={activeTab} onTabSelect={onTabSelect}>
@@ -899,13 +869,7 @@ export const ResultsView: React.FC<ResultsViewProps> = ({
/> />
)} )}
{activeTab === ResultsTabs.QueryStats && <QueryStatsTab queryResults={queryResults} />} {activeTab === ResultsTabs.QueryStats && <QueryStatsTab queryResults={queryResults} />}
{activeTab === ResultsTabs.IndexAdvisor && ( {activeTab === ResultsTabs.IndexAdvisor && <IndexAdvisorTab />}
<IndexAdvisorTab
queryText={queryText}
databaseId={databaseId}
containerId={containerId}
/>
)}
</div> </div>
</div> </div>
); );