mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-02-16 17:25:58 +00:00
Fix lint query utils (#487)
* Fix Lint errors in QueryUtils * Format * Simplify diff Co-authored-by: Your Name <you@example.com> Co-authored-by: Steve Faulkner <southpolesteve@gmail.com> Co-authored-by: Steve Faulkner <471400+southpolesteve@users.noreply.github.com> Co-authored-by: Jordi Bunster <jbunster@microsoft.com>
This commit is contained in:
parent
fad3a08fdf
commit
343e82c102
@ -257,7 +257,6 @@ src/TokenProviders/PortalTokenProvider.ts
|
|||||||
src/TokenProviders/TokenProviderFactory.ts
|
src/TokenProviders/TokenProviderFactory.ts
|
||||||
src/Utils/PricingUtils.test.ts
|
src/Utils/PricingUtils.test.ts
|
||||||
src/Utils/QueryUtils.test.ts
|
src/Utils/QueryUtils.test.ts
|
||||||
src/Utils/QueryUtils.ts
|
|
||||||
src/applyExplorerBindings.ts
|
src/applyExplorerBindings.ts
|
||||||
src/global.d.ts
|
src/global.d.ts
|
||||||
src/setupTests.ts
|
src/setupTests.ts
|
||||||
|
@ -6,7 +6,7 @@ import Explorer from "../Explorer/Explorer";
|
|||||||
import DocumentsTab from "../Explorer/Tabs/DocumentsTab";
|
import DocumentsTab from "../Explorer/Tabs/DocumentsTab";
|
||||||
import DocumentId from "../Explorer/Tree/DocumentId";
|
import DocumentId from "../Explorer/Tree/DocumentId";
|
||||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
import { QueryUtils } from "../Utils/QueryUtils";
|
import * as QueryUtils from "../Utils/QueryUtils";
|
||||||
import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants";
|
import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
import { queryDocumentsPage } from "./dataAccess/queryDocumentsPage";
|
import { queryDocumentsPage } from "./dataAccess/queryDocumentsPage";
|
||||||
|
@ -11,7 +11,7 @@ import editable from "../../Common/EditableUtility";
|
|||||||
import * as HeadersUtility from "../../Common/HeadersUtility";
|
import * as HeadersUtility from "../../Common/HeadersUtility";
|
||||||
import TabsBase from "./TabsBase";
|
import TabsBase from "./TabsBase";
|
||||||
import { DocumentsGridMetrics } from "../../Common/Constants";
|
import { DocumentsGridMetrics } from "../../Common/Constants";
|
||||||
import { QueryUtils } from "../../Utils/QueryUtils";
|
import * as QueryUtils from "../../Utils/QueryUtils";
|
||||||
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import NewDocumentIcon from "../../../images/NewDocument.svg";
|
import NewDocumentIcon from "../../../images/NewDocument.svg";
|
||||||
|
@ -9,7 +9,7 @@ import * as HeadersUtility from "../../Common/HeadersUtility";
|
|||||||
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
|
import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
|
||||||
import { QueryUtils } from "../../Utils/QueryUtils";
|
import * as QueryUtils from "../../Utils/QueryUtils";
|
||||||
import SaveQueryIcon from "../../../images/save-cosmos.svg";
|
import SaveQueryIcon from "../../../images/save-cosmos.svg";
|
||||||
|
|
||||||
import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
|
import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
|
||||||
|
@ -2,7 +2,7 @@ import * as DataModels from "../Contracts/DataModels";
|
|||||||
import * as Q from "q";
|
import * as Q from "q";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
import { QueryUtils } from "./QueryUtils";
|
import * as QueryUtils from "./QueryUtils";
|
||||||
|
|
||||||
describe("Query Utils", () => {
|
describe("Query Utils", () => {
|
||||||
function generatePartitionKeyForPath(path: string): DataModels.PartitionKey {
|
function generatePartitionKeyForPath(path: string): DataModels.PartitionKey {
|
||||||
|
@ -1,118 +1,114 @@
|
|||||||
import Q from "q";
|
|
||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
|
|
||||||
export class QueryUtils {
|
export function buildDocumentsQuery(
|
||||||
public static buildDocumentsQuery(
|
filter: string,
|
||||||
filter: string,
|
partitionKeyProperty: string,
|
||||||
partitionKeyProperty: string,
|
partitionKey: DataModels.PartitionKey
|
||||||
partitionKey: DataModels.PartitionKey
|
): string {
|
||||||
): string {
|
let query = partitionKeyProperty
|
||||||
let query: string = partitionKeyProperty
|
? `select c.id, c._self, c._rid, c._ts, ${buildDocumentsQueryPartitionProjections(
|
||||||
? `select c.id, c._self, c._rid, c._ts, ${QueryUtils.buildDocumentsQueryPartitionProjections(
|
"c",
|
||||||
"c",
|
partitionKey
|
||||||
partitionKey
|
)} as _partitionKeyValue from c`
|
||||||
)} as _partitionKeyValue from c`
|
: `select c.id, c._self, c._rid, c._ts from c`;
|
||||||
: `select c.id, c._self, c._rid, c._ts from c`;
|
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
query += " " + filter;
|
query += " " + filter;
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static buildDocumentsQueryPartitionProjections(
|
return query;
|
||||||
collectionAlias: string,
|
|
||||||
partitionKey: DataModels.PartitionKey
|
|
||||||
): string {
|
|
||||||
if (!partitionKey) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g., path /order/id will be projected as c["order"]["id"],
|
|
||||||
// to escape any property names that match a keyword
|
|
||||||
let projections = [];
|
|
||||||
for (let index in partitionKey.paths) {
|
|
||||||
// TODO: Handle "/" in partition key definitions
|
|
||||||
const projectedProperties: string[] = partitionKey.paths[index].split("/").slice(1);
|
|
||||||
let projectedProperty: string = "";
|
|
||||||
|
|
||||||
projectedProperties.forEach((property: string) => {
|
|
||||||
const projection = property.trim();
|
|
||||||
if (projection.length > 0 && projection.charAt(0) != "'" && projection.charAt(0) != '"') {
|
|
||||||
projectedProperty = projectedProperty + `["${projection}"]`;
|
|
||||||
} else if (projection.length > 0 && projection.charAt(0) == "'") {
|
|
||||||
// trim single quotes and escape double quotes
|
|
||||||
const projectionSlice = projection.slice(1, projection.length - 1);
|
|
||||||
projectedProperty =
|
|
||||||
projectedProperty + `["${projectionSlice.replace(/\\"/g, '"').replace(/"/g, '\\\\\\"')}"]`;
|
|
||||||
} else {
|
|
||||||
projectedProperty = projectedProperty + `[${projection}]`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
projections.push(`${collectionAlias}${projectedProperty}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return projections.join(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async queryPagesUntilContentPresent(
|
|
||||||
firstItemIndex: number,
|
|
||||||
queryItems: (itemIndex: number) => Promise<ViewModels.QueryResults>
|
|
||||||
): Promise<ViewModels.QueryResults> {
|
|
||||||
let roundTrips: number = 0;
|
|
||||||
let netRequestCharge: number = 0;
|
|
||||||
const doRequest = async (itemIndex: number): Promise<ViewModels.QueryResults> => {
|
|
||||||
const results: ViewModels.QueryResults = await queryItems(itemIndex);
|
|
||||||
roundTrips = roundTrips + 1;
|
|
||||||
results.roundTrips = roundTrips;
|
|
||||||
results.requestCharge = Number(results.requestCharge) + netRequestCharge;
|
|
||||||
netRequestCharge = Number(results.requestCharge);
|
|
||||||
const resultsMetadata: ViewModels.QueryResultsMetadata = {
|
|
||||||
hasMoreResults: results.hasMoreResults,
|
|
||||||
itemCount: results.itemCount,
|
|
||||||
firstItemIndex: results.firstItemIndex,
|
|
||||||
lastItemIndex: results.lastItemIndex,
|
|
||||||
};
|
|
||||||
if (resultsMetadata.itemCount === 0 && resultsMetadata.hasMoreResults) {
|
|
||||||
return await doRequest(resultsMetadata.lastItemIndex);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
return await doRequest(firstItemIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async queryAllPages(
|
|
||||||
queryItems: (itemIndex: number) => Promise<ViewModels.QueryResults>
|
|
||||||
): Promise<ViewModels.QueryResults> {
|
|
||||||
const queryResults: ViewModels.QueryResults = {
|
|
||||||
documents: [],
|
|
||||||
activityId: undefined,
|
|
||||||
hasMoreResults: false,
|
|
||||||
itemCount: 0,
|
|
||||||
firstItemIndex: 0,
|
|
||||||
lastItemIndex: 0,
|
|
||||||
requestCharge: 0,
|
|
||||||
roundTrips: 0,
|
|
||||||
};
|
|
||||||
const doRequest = async (itemIndex: number): Promise<ViewModels.QueryResults> => {
|
|
||||||
const results: ViewModels.QueryResults = await queryItems(itemIndex);
|
|
||||||
const { requestCharge, hasMoreResults, itemCount, lastItemIndex, documents } = results;
|
|
||||||
queryResults.roundTrips = queryResults.roundTrips + 1;
|
|
||||||
queryResults.requestCharge = Number(queryResults.requestCharge) + Number(requestCharge);
|
|
||||||
queryResults.hasMoreResults = hasMoreResults;
|
|
||||||
queryResults.itemCount = queryResults.itemCount + itemCount;
|
|
||||||
queryResults.lastItemIndex = lastItemIndex;
|
|
||||||
queryResults.documents = queryResults.documents.concat(documents);
|
|
||||||
if (queryResults.hasMoreResults) {
|
|
||||||
return doRequest(queryResults.lastItemIndex + 1);
|
|
||||||
}
|
|
||||||
return queryResults;
|
|
||||||
};
|
|
||||||
|
|
||||||
return doRequest(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildDocumentsQueryPartitionProjections(
|
||||||
|
collectionAlias: string,
|
||||||
|
partitionKey?: DataModels.PartitionKey
|
||||||
|
): string {
|
||||||
|
if (!partitionKey) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// e.g., path /order/id will be projected as c["order"]["id"],
|
||||||
|
// to escape any property names that match a keyword
|
||||||
|
const projections = [];
|
||||||
|
for (const index in partitionKey.paths) {
|
||||||
|
// TODO: Handle "/" in partition key definitions
|
||||||
|
const projectedProperties: string[] = partitionKey.paths[index].split("/").slice(1);
|
||||||
|
let projectedProperty = "";
|
||||||
|
|
||||||
|
projectedProperties.forEach((property: string) => {
|
||||||
|
const projection = property.trim();
|
||||||
|
if (projection.length > 0 && projection.charAt(0) !== "'" && projection.charAt(0) !== '"') {
|
||||||
|
projectedProperty += `["${projection}"]`;
|
||||||
|
} else if (projection.length > 0 && projection.charAt(0) === "'") {
|
||||||
|
// trim single quotes and escape double quotes
|
||||||
|
const projectionSlice = projection.slice(1, projection.length - 1);
|
||||||
|
projectedProperty += `["${projectionSlice.replace(/\\"/g, '"').replace(/"/g, '\\\\\\"')}"]`;
|
||||||
|
} else {
|
||||||
|
projectedProperty += `[${projection}]`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
projections.push(`${collectionAlias}${projectedProperty}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return projections.join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
export const queryPagesUntilContentPresent = async (
|
||||||
|
firstItemIndex: number,
|
||||||
|
queryItems: (itemIndex: number) => Promise<ViewModels.QueryResults>
|
||||||
|
): Promise<ViewModels.QueryResults> => {
|
||||||
|
let roundTrips = 0;
|
||||||
|
let netRequestCharge = 0;
|
||||||
|
const doRequest = async (itemIndex: number): Promise<ViewModels.QueryResults> => {
|
||||||
|
const results = await queryItems(itemIndex);
|
||||||
|
roundTrips = roundTrips + 1;
|
||||||
|
results.roundTrips = roundTrips;
|
||||||
|
results.requestCharge = Number(results.requestCharge) + netRequestCharge;
|
||||||
|
netRequestCharge = Number(results.requestCharge);
|
||||||
|
const resultsMetadata = {
|
||||||
|
hasMoreResults: results.hasMoreResults,
|
||||||
|
itemCount: results.itemCount,
|
||||||
|
firstItemIndex: results.firstItemIndex,
|
||||||
|
lastItemIndex: results.lastItemIndex,
|
||||||
|
};
|
||||||
|
if (resultsMetadata.itemCount === 0 && resultsMetadata.hasMoreResults) {
|
||||||
|
return await doRequest(resultsMetadata.lastItemIndex);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
return await doRequest(firstItemIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const queryAllPages = async (
|
||||||
|
queryItems: (itemIndex: number) => Promise<ViewModels.QueryResults>
|
||||||
|
): Promise<ViewModels.QueryResults> => {
|
||||||
|
const queryResults: ViewModels.QueryResults = {
|
||||||
|
documents: [],
|
||||||
|
activityId: undefined,
|
||||||
|
hasMoreResults: false,
|
||||||
|
itemCount: 0,
|
||||||
|
firstItemIndex: 0,
|
||||||
|
lastItemIndex: 0,
|
||||||
|
requestCharge: 0,
|
||||||
|
roundTrips: 0,
|
||||||
|
};
|
||||||
|
const doRequest = async (itemIndex: number): Promise<ViewModels.QueryResults> => {
|
||||||
|
const results = await queryItems(itemIndex);
|
||||||
|
const { requestCharge, hasMoreResults, itemCount, lastItemIndex, documents } = results;
|
||||||
|
queryResults.roundTrips = queryResults.roundTrips + 1;
|
||||||
|
queryResults.requestCharge = Number(queryResults.requestCharge) + Number(requestCharge);
|
||||||
|
queryResults.hasMoreResults = hasMoreResults;
|
||||||
|
queryResults.itemCount = queryResults.itemCount + itemCount;
|
||||||
|
queryResults.lastItemIndex = lastItemIndex;
|
||||||
|
queryResults.documents = queryResults.documents.concat(documents);
|
||||||
|
if (queryResults.hasMoreResults) {
|
||||||
|
return doRequest(queryResults.lastItemIndex + 1);
|
||||||
|
}
|
||||||
|
return queryResults;
|
||||||
|
};
|
||||||
|
|
||||||
|
return doRequest(0);
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user