+
+
{{ t("grid.querySuccess") }}
diff --git a/apps/desktop/src/components/layout/ContentArea.vue b/apps/desktop/src/components/layout/ContentArea.vue
index 307a227c91..46b0a7a687 100644
--- a/apps/desktop/src/components/layout/ContentArea.vue
+++ b/apps/desktop/src/components/layout/ContentArea.vue
@@ -2,13 +2,14 @@
import { computed, ref, defineAsyncComponent, watch, nextTick, onMounted, onUnmounted } from "vue";
import type { CSSProperties } from "vue";
import { useI18n } from "vue-i18n";
-import { Check, Columns3, Loader2, Search, Square, Bot, GitBranch, BarChart3, TableProperties, ChevronDown, ChevronUp, Inbox, RefreshCcw, Wrench, ListChecks, Download, X } from "@lucide/vue";
+import { Check, Columns3, Loader2, Search, Bot, GitBranch, BarChart3, TableProperties, ChevronDown, ChevronUp, Inbox, RefreshCcw, Wrench, ListChecks, Download, X } from "@lucide/vue";
import { Splitpanes, Pane } from "splitpanes";
import "splitpanes/dist/splitpanes.css";
import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Switch } from "@/components/ui/switch";
import LightTooltip from "@/components/ui/LightTooltip.vue";
+import QueryLoadingState from "@/components/common/QueryLoadingState.vue";
import QueryEditor from "@/components/editor/QueryEditor.vue";
import ColumnInfoPanel from "@/components/editor/ColumnInfoPanel.vue";
import type { ColumnInfo } from "@/components/editor/ColumnInfoPanel.vue";
@@ -700,18 +701,16 @@ defineExpose({ focusSearch, refreshData, handleModRTarget });
-
-
-
- {{ t(queryExecutionLabelKey(activeTab)) }}
- · {{ queryRunningElapsedSeconds }}s
-
-
-
+
{{ t("editor.pressToExecute", { mod: shortcutModifier }) }}
{{ t("editor.pressToSaveSql", { mod: shortcutModifier }) }}
@@ -847,18 +846,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget });
@paginate="(offset: number, limit: number, whereInput?: string, orderBy?: string) => emit('paginate', offset, limit, whereInput, orderBy)"
@sort="(column: string, columnIndex: number, direction: 'asc' | 'desc' | null, whereInput?: string) => emit('sort', column, columnIndex, direction, whereInput)"
/>
-
-
-
- {{ t(queryExecutionLabelKey(activeTab)) }}
- · {{ queryRunningElapsedSeconds }}s
-
-
-
+
{{ t("grid.dataUnavailable") }}
diff --git a/apps/desktop/src/lib/http.ts b/apps/desktop/src/lib/http.ts
index fbc06f5e4e..b755c382a9 100644
--- a/apps/desktop/src/lib/http.ts
+++ b/apps/desktop/src/lib/http.ts
@@ -545,7 +545,8 @@ export async function executeInTransaction(connectionId: string, database: strin
}
export async function cancelQuery(executionId: string): Promise
{
- return post("/api/query/cancel", { executionId });
+ const result = await post("/api/query/cancel", { executionId });
+ return typeof result === "boolean" ? result : result.cancelled === true;
}
export async function analyzeSqlReferences(sql: string, dialect?: string): Promise {
@@ -1389,16 +1390,16 @@ export async function elasticsearchListIndices(connectionId: string): Promise {
- return post("/api/mongo/find-documents", { connectionId, database, collection, skip, limit, filter, sort });
+export async function mongoFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string, executionId?: string): Promise {
+ return post("/api/mongo/find-documents", { connectionId, database, collection, skip, limit, filter, sort, executionId });
}
-export async function documentFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string): Promise {
- return post("/api/document-store/find-documents", { connectionId, database, collection, skip, limit, filter, sort });
+export async function documentFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string, executionId?: string): Promise {
+ return post("/api/document-store/find-documents", { connectionId, database, collection, skip, limit, filter, sort, executionId });
}
-export async function mongoAggregateDocuments(connectionId: string, database: string, collection: string, pipelineJson: string, maxRows?: number): Promise {
- return post("/api/mongo/aggregate-documents", { connectionId, database, collection, pipelineJson, maxRows });
+export async function mongoAggregateDocuments(connectionId: string, database: string, collection: string, pipelineJson: string, maxRows?: number, executionId?: string): Promise {
+ return post("/api/mongo/aggregate-documents", { connectionId, database, collection, pipelineJson, maxRows, executionId });
}
export async function mongoInsertDocument(connectionId: string, database: string, collection: string, docJson: string): Promise {
diff --git a/apps/desktop/src/lib/tauri.ts b/apps/desktop/src/lib/tauri.ts
index 8509163520..ee5c1008d7 100644
--- a/apps/desktop/src/lib/tauri.ts
+++ b/apps/desktop/src/lib/tauri.ts
@@ -1268,16 +1268,16 @@ export async function elasticsearchListIndices(connectionId: string): Promise {
- return invoke("mongo_find_documents", { connectionId, database, collection, skip, limit, filter, sort });
+export async function mongoFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string, executionId?: string): Promise {
+ return invoke("mongo_find_documents", { connectionId, database, collection, skip, limit, filter, sort, executionId });
}
-export async function documentFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string): Promise {
- return invoke("document_find_documents", { connectionId, database, collection, skip, limit, filter, sort });
+export async function documentFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string, executionId?: string): Promise {
+ return invoke("document_find_documents", { connectionId, database, collection, skip, limit, filter, sort, executionId });
}
-export async function mongoAggregateDocuments(connectionId: string, database: string, collection: string, pipelineJson: string, maxRows?: number): Promise {
- return invoke("mongo_aggregate_documents", { connectionId, database, collection, pipelineJson, maxRows });
+export async function mongoAggregateDocuments(connectionId: string, database: string, collection: string, pipelineJson: string, maxRows?: number, executionId?: string): Promise {
+ return invoke("mongo_aggregate_documents", { connectionId, database, collection, pipelineJson, maxRows, executionId });
}
export async function mongoInsertDocument(connectionId: string, database: string, collection: string, docJson: string): Promise {
diff --git a/apps/desktop/src/stores/queryStore.ts b/apps/desktop/src/stores/queryStore.ts
index 4aa26df1f3..1c44266cb9 100644
--- a/apps/desktop/src/stores/queryStore.ts
+++ b/apps/desktop/src/stores/queryStore.ts
@@ -1225,7 +1225,7 @@ export const useQueryStore = defineStore("query", () => {
if (mongoFind) {
await connStore.ensureConnected(tab.connectionId);
console.info("[DBX][executeTabSql:mongo-find:start]", { traceId, collection: mongoFind.collection });
- const result = await api.mongoFindDocuments(tab.connectionId, tab.database, mongoFind.collection, mongoFind.skip, mongoFind.limit, mongoFind.filter, mongoFind.sort);
+ const result = await api.mongoFindDocuments(tab.connectionId, tab.database, mongoFind.collection, mongoFind.skip, mongoFind.limit, mongoFind.filter, mongoFind.sort, executionId);
console.info("[DBX][executeTabSql:mongo-find:done]", {
traceId,
rowCount: result.documents.length,
@@ -1252,7 +1252,7 @@ export const useQueryStore = defineStore("query", () => {
if (mongoCount) {
await connStore.ensureConnected(tab.connectionId);
console.info("[DBX][executeTabSql:mongo-count:start]", { traceId, collection: mongoCount.collection });
- const result = await api.mongoFindDocuments(tab.connectionId, tab.database, mongoCount.collection, 0, 1, mongoCount.filter);
+ const result = await api.mongoFindDocuments(tab.connectionId, tab.database, mongoCount.collection, 0, 1, mongoCount.filter, undefined, executionId);
console.info("[DBX][executeTabSql:mongo-count:done]", {
traceId,
total: result.total,
@@ -1283,7 +1283,7 @@ export const useQueryStore = defineStore("query", () => {
}
await connStore.ensureConnected(tab.connectionId);
console.info("[DBX][executeTabSql:mongo-aggregate:start]", { traceId, collection: mongoAggregate.collection });
- const result = await api.mongoAggregateDocuments(tab.connectionId, tab.database, mongoAggregate.collection, mongoAggregate.pipeline, pageLimit);
+ const result = await api.mongoAggregateDocuments(tab.connectionId, tab.database, mongoAggregate.collection, mongoAggregate.pipeline, pageLimit, executionId);
console.info("[DBX][executeTabSql:mongo-aggregate:done]", {
traceId,
rowCount: result.documents.length,
diff --git a/crates/dbx-web/src/routes/mongo.rs b/crates/dbx-web/src/routes/mongo.rs
index b09d26315a..0a7fede627 100644
--- a/crates/dbx-web/src/routes/mongo.rs
+++ b/crates/dbx-web/src/routes/mongo.rs
@@ -1,3 +1,4 @@
+use std::future::Future;
use std::sync::Arc;
use axum::extract::State;
@@ -7,6 +8,26 @@ use serde::Deserialize;
use crate::error::AppError;
use crate::state::WebState;
+async fn run_cancellable(state: &Arc, execution_id: Option, future: F) -> Result
+where
+ F: Future