Skip to content

Commit

Permalink
merge branch main
Browse files Browse the repository at this point in the history
  • Loading branch information
lokesh-couchbase committed Oct 30, 2023
2 parents 8e05e44 + 9487a86 commit 1d4fa73
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 71 deletions.
26 changes: 11 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -608,37 +608,37 @@
"command": "vscode-couchbase.runQuery",
"key": "ctrl+shift+e",
"mac": "cmd+shift+e",
"when": "editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/ "
"when": "(editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/) && !isKVCluster"
}
],
"menus": {
"editor/title": [
{
"command": "vscode-couchbase.runQuery",
"category": "Couchbase",
"when": "editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/ ",
"when": "(editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/) && !isKVCluster",
"group": "navigation@1"
},
{
"title": "Query Context",
"command": "vscode-couchbase.queryContext",
"category": "Couchbase",
"group": "navigation@2",
"when": "editorLangId == sqlpp || resourceFilename =~ /\\.sqlpp$/"
"when": "(editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/) && !isKVCluster"
},
{
"title": "Show Favorite Queries",
"command": "vscode-couchbase.showFavoriteQueries",
"category": "Couchbase",
"group": "navigation@3",
"when": "editorLangId == sqlpp || resourceFilename =~ /\\.sqlpp$/"
"when": "(editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/) && !isKVCluster"
},
{
"title": "Mark Favorite Query",
"command": "vscode-couchbase.markFavoriteQuery",
"category": "Couchbase",
"group": "navigation@4",
"when": "editorLangId == sqlpp || resourceFilename =~ /\\.sqlpp$/"
"when": "(editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/) && !isKVCluster"
},
{
"title": "Refresh Cluster Overview",
Expand All @@ -651,7 +651,7 @@
"editor/context": [
{
"command": "vscode-couchbase.runQuery",
"when": "editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/ ",
"when": "(editorLangId == sqlpp || resourceFilename =~ /.sqlpp$/) && !isKVCluster",
"group": "navigation@1"
}
],
Expand Down Expand Up @@ -802,22 +802,18 @@
},
{
"command": "vscode-couchbase.openQueryNotebook",
"when": "view == couchbase && viewItem == active_connection",
"when": "view == couchbase && viewItem == active_connection && !isKVCluster",
"group": "workbench@2"
},
{
"command": "vscode-couchbase.openQueryWorkbench",
"when": "view == couchbase && viewItem == active_connection",
"when": "view == couchbase && viewItem == active_connection && !isKVCluster",
"group": "workbench@1"
},
{
"submenu": "vscode-couchbase.toolsMenu",
"when": "view == couchbase && viewItem == active_connection"
},
{
"submenu": "vscode-couchbase.toolsMenu",
"when": "view == couchbase && viewItem == active_connection"
},
{
"command": "vscode-couchbase.useClusterConnection",
"when": "view == couchbase && viewItem == connection"
Expand All @@ -834,7 +830,7 @@
},
{
"command": "vscode-couchbase.filterDocuments",
"when": "view == couchbase && (viewItem == collection || viewItem == default_collection)",
"when": "view == couchbase && (viewItem == collection || viewItem == default_collection) && !isKVCluster",
"group": "secondary"
},
{
Expand Down Expand Up @@ -898,12 +894,12 @@
},
{
"command": "vscode-couchbase.deleteQueryHistoryItem",
"when": "view == query-history",
"when": "view == query-history && !isKVCluster",
"group": "inline"
},
{
"command": "vscode-couchbase.copyQueryHistoryItem",
"when": "view == query-history",
"when": "view == query-history && !isKVCluster",
"group": "inline"
}
],
Expand Down
23 changes: 18 additions & 5 deletions src/commands/documents/getDocumentMetaData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,30 @@ import { logger } from "../../logger/logger";
import { getDocumentMetaDataView } from "../../webViews/metaData.webview";
import DocumentNode from "../../model/DocumentNode";
import { Constants } from "../../util/constants";
import { hasQueryService } from "../../util/common";
import { CouchbaseRestAPI } from "../../util/apis/CouchbaseRestAPI";

export const getDocumentMetaData = async (node: DocumentNode, context: vscode.ExtensionContext) => {
const connection = Memory.state.get<IConnection>(Constants.ACTIVE_CONNECTION);
if (!connection) {
return;
}
try {
const result = await connection.cluster?.query(
`SELECT META(b).* FROM \`${node.bucketName}\`.\`${node.scopeName}\`.\`${node.collectionName}\` b WHERE META(b).id = \"${node.documentName}\"`
);
let result;
if (hasQueryService(connection.services)) {
try {
result = await connection.cluster?.query(
`SELECT META(b).* FROM \`${node.bucketName}\`.\`${node.scopeName}\`.\`${node.collectionName}\` b WHERE META(b).id = \"${node.documentName}\"`
);
result = result?.rows;
} catch {
const couchbaseRestAPI = new CouchbaseRestAPI(connection);
result = await couchbaseRestAPI.getKVDocumentMetaData(node.bucketName, node.scopeName, node.collectionName, node.documentName);
}
} else {
const couchbaseRestAPI = new CouchbaseRestAPI(connection);
result = await couchbaseRestAPI.getKVDocumentMetaData(node.bucketName, node.scopeName, node.collectionName, node.documentName);
}
const viewType = `${connection.url}.${node.bucketName}.${node.scopeName}.${node.collectionName}.${node.documentName}`;
let currentPanel: vscode.WebviewPanel | undefined = vscode.window.createWebviewPanel(
viewType,
Expand All @@ -44,8 +58,7 @@ export const getDocumentMetaData = async (node: DocumentNode, context: vscode.Ex
light: vscode.Uri.file(path.join(__filename, "..", "..", "images", "light", "document.svg")),
dark: vscode.Uri.file(path.join(__filename, "..", "..", "images", "dark", "document.svg"))
};
currentPanel.webview.html = getDocumentMetaDataView(result?.rows);

currentPanel.webview.html = getDocumentMetaDataView(result);
currentPanel.onDidDispose(
() => {
currentPanel = undefined;
Expand Down
20 changes: 15 additions & 5 deletions src/commands/documents/openDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,27 @@ export const openDocument = async (documentNode: DocumentNode, clusterConnection
.scope(documentNode.scopeName)
.collection(documentNode.collectionName)
.get(documentNode.documentName);

if (result?.content instanceof Uint8Array || result?.content instanceof Uint16Array || result?.content instanceof Uint32Array) {
vscode.window.showInformationMessage("Unable to open document: It is not a valid JSON document", { modal: true });
return false;
}
const uri = vscode.Uri.parse(
`couchbase:/${documentNode.bucketName}/${documentNode.scopeName}/Collections/${documentNode.collectionName}/${documentNode.documentName}.json`
);
if (result) {
uriToCasMap.set(uri.toString(), result.cas.toString());
}
memFs.writeFile(
uri,
Buffer.from(JSON.stringify(result?.content, null, 2)),
{ create: true, overwrite: true }
);
try {
memFs.writeFile(
uri,
Buffer.from(JSON.stringify(result?.content, null, 2)),
{ create: true, overwrite: true }
);
} catch (error) {
vscode.window.showInformationMessage("Unable to open document: It is not a valid JSON document", { modal: true });
return false;
}
const document = await vscode.workspace.openTextDocument(uri);
await vscode.window.showTextDocument(document, { preview: false });
return true;
Expand Down
83 changes: 49 additions & 34 deletions src/model/CollectionNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { IConnection } from "../types/IConnection";
import { INode } from "../types/INode";
import DocumentNode from "./DocumentNode";
import { PagerNode } from "./PagerNode";
import { abbreviateCount } from "../util/common";
import { abbreviateCount, hasQueryService } from "../util/common";
import { ParsingFailureError, PlanningFailureError } from "couchbase";
import InformationNode from "./InformationNode";
import { Memory } from "../util/util";
Expand All @@ -29,6 +29,7 @@ import { getActiveConnection } from "../util/connections";
import { Commands } from "../commands/extensionCommands/commands";
import { IndexDirectory } from "./IndexDirectory";
import { logger } from "../logger/logger";
import { CouchbaseRestAPI } from "../util/apis/CouchbaseRestAPI";

export default class CollectionNode implements INode {
constructor(
Expand Down Expand Up @@ -89,18 +90,24 @@ export default class CollectionNode implements INode {
[],
vscode.TreeItemCollapsibleState.None
);

documentList.push(indexItem);
documentList.push(
new SchemaDirectory(
this,
this.connection,
"Schema",
this.bucketName,
this.scopeName,
this.collectionName
)
);
const connection = getActiveConnection();
if (!connection) {
return [];
}
const isQueryServicesEnable = hasQueryService(connection?.services);
if (isQueryServicesEnable) {
documentList.push(indexItem);
documentList.push(
new SchemaDirectory(
this,
this.connection,
"Schema",
this.bucketName,
this.scopeName,
this.collectionName
)
);
}
// TODO: default limit could be managed as user settings / preference
let result;
// A primary index is required for database querying. If one is present, a result will be obtained.
Expand All @@ -112,27 +119,35 @@ export default class CollectionNode implements INode {
if (docFilter && docFilter.filter.length > 0) {
filter = docFilter.filter;
}
const connection = getActiveConnection();
try {
result = await connection?.cluster?.query(
`SELECT RAW META().id FROM \`${this.bucketName}\`.\`${this.scopeName
}\`.\`${this.collectionName}\` ${filter.length > 0 ? "WHERE " + filter : ""
} LIMIT ${this.limit}`
);
} catch (err) {
if (err instanceof PlanningFailureError) {
const infoNode: InformationNode = new InformationNode(
"No indexes available, click to create one",
"No indexes available to list the documents in this collection",
{
command: Commands.checkAndCreatePrimaryIndex,
title: "Create Primary Index",
arguments: [this],
}
const couchbbaseRestAPI = new CouchbaseRestAPI(connection);
if (!hasQueryService(connection?.services!)) {
result = await couchbbaseRestAPI.getKVDocuments(this.bucketName, this.scopeName, this.collectionName, 0, this.limit);
result.rows = result.rows.map((item: any) => item.id);
}
else {
try {
result = await connection?.cluster?.query(
`SELECT RAW META().id FROM \`${this.bucketName}\`.\`${this.scopeName
}\`.\`${this.collectionName}\` ${filter.length > 0 ? "WHERE " + filter : ""
} LIMIT ${this.limit}`
);
documentList.push(infoNode);
} else if (err instanceof ParsingFailureError) {
logger.error(`In Collection Node: ${this.collectionName}: Parsing Failed: Incorrect filter definition`);
} catch (err) {
if (err instanceof PlanningFailureError) {
const infoNode: InformationNode = new InformationNode(
"No indexes available, click to create one",
"No indexes available to list the documents in this collection",
{
command: Commands.checkAndCreatePrimaryIndex,
title: "Create Primary Index",
arguments: [this],
}
);
documentList.push(infoNode);
result = await couchbbaseRestAPI.getKVDocuments(this.bucketName, this.scopeName, this.collectionName, 0, this.limit);
result.rows = result.rows.map((item: any) => item.id);
} else if (err instanceof ParsingFailureError) {
logger.error(`In Collection Node: ${this.collectionName}: Parsing Failed: Incorrect filter definition`);
}
}
}
result?.rows.forEach((documentName: string) => {
Expand All @@ -151,7 +166,7 @@ export default class CollectionNode implements INode {
// TODO: add local only (un-synchronized) files to documentList

// Checking document list length with 2 as Schema and index Directory are always present
if (documentList.length === 2) {
if (((!isQueryServicesEnable && documentList.length === 0)) || documentList.length === 2) {
documentList.push(new InformationNode("No Documents found"));
} else if (this.documentCount > documentList.length) {
documentList.push(new PagerNode(this));
Expand Down
27 changes: 20 additions & 7 deletions src/model/ScopeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import CollectionNode from "./CollectionNode";
import { logger } from "../logger/logger";
import InformationNode from "./InformationNode";
import { ParsingFailureError, PlanningFailureError } from "couchbase";
import { hasQueryService } from "../util/common";
import { CouchbaseRestAPI } from "../util/apis/CouchbaseRestAPI";

export class ScopeNode implements INode {
constructor(
Expand Down Expand Up @@ -62,23 +64,34 @@ export class ScopeNode implements INode {
* @returns Two Directory one contains Index definitions and other contains Collections
* */
public async getChildren(): Promise<INode[]> {
const connection = getActiveConnection();
if (!connection) {
return [];
}
const collectionList: any[] = [];
const couchbaseRestAPI = new CouchbaseRestAPI(connection);
const KVCollectionCount: Map<string, number> = await couchbaseRestAPI.getKVDocumentCount(this.bucketName, this.scopeName);

for (const collection of this.collections) {
try {
const docFilter = Memory.state.get<IFilterDocuments>(
`filterDocuments-${this.connection.connectionIdentifier}-${this.bucketName}-${this.scopeName}-${collection.name}`
);
const filter: string =
docFilter && docFilter.filter.length > 0 ? docFilter.filter : "";
const connection = getActiveConnection();
let rowCount = 0;
try {
const queryResult = await connection?.cluster?.query(
`select count(1) as count from \`${this.bucketName}\`.\`${this.scopeName
}\`.\`${collection.name}\` ${filter.length > 0 ? "WHERE " + filter : ""
};`
);
rowCount = queryResult?.rows[0].count;
if (!hasQueryService(connection?.services) || filter === "") {
rowCount = KVCollectionCount.get(`kv_collection_item_count-${this.bucketName}-${this.scopeName}-${collection.name}`) ?? 0;
}
else {
const queryResult = await connection?.cluster?.query(
`select count(1) as count from \`${this.bucketName}\`.\`${this.scopeName
}\`.\`${collection.name}\` ${filter.length > 0 ? "WHERE " + filter : ""
};`
);
rowCount = queryResult?.rows[0].count;
}
} catch (err: any) {
if (err instanceof PlanningFailureError) {
vscode.window.showErrorMessage(
Expand Down
1 change: 1 addition & 0 deletions src/types/IConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ export interface IConnection {
readonly password?: string;
readonly connectionIdentifier: string;
readonly isSecure: boolean;
services?: string[];
cluster?: Cluster;
}
23 changes: 21 additions & 2 deletions src/util/OverviewClusterUtils/ClusterOverviewGeneralTab.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
/*
* Copyright 2011-2020 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { IKeyValuePair } from "../../types/IKeyValuePair";
import { fmtByte, formatServices, mbToGb } from "./OverviewClusterHelper";
import { fmtByte, formatServices, mbToGb } from "./OverviewClusterHelper";
import { ServerOverview } from "../apis/ServerOverview";
import { Constants } from "../constants";

Expand All @@ -23,7 +38,7 @@ export const getGeneralClusterDetails = (serverOverview: ServerOverview | undefi
// Services
details.push({
key: Constants.SERVICES,
value: formatServices(serverOverview.getNodes()[0].services.join(', ').toString()) || "NA"
value: formatServices(getServices(serverOverview).join(', ').toString()) || "NA"
});

// Nodes
Expand All @@ -45,6 +60,10 @@ export const getGeneralClusterDetails = (serverOverview: ServerOverview | undefi
return details;
};

export const getServices = (serverOverview: ServerOverview): string[] => {
return serverOverview.getNodes()[0].services;
};

export const getGeneralQuotaDetails = (serverOverview: ServerOverview | undefined): IKeyValuePair[] => {
let details: IKeyValuePair[] = [];
if (serverOverview === undefined) {
Expand Down
Loading

0 comments on commit 1d4fa73

Please sign in to comment.