fix(neo4j): support table querying and editing

This commit is contained in:
t8y2
2026-05-13 19:30:00 +08:00
parent 2f4c50dc1e
commit 0172ee50be
11 changed files with 303 additions and 15 deletions
+10 -3
View File
@@ -826,7 +826,7 @@ function currentWhereInput(): string | undefined {
function currentOrderBy(): string | undefined {
return (
orderByInput.value.trim() ||
(sortCol.value ? `${quoteIdent(sortCol.value)} ${sortDir.value.toUpperCase()}` : undefined)
(sortCol.value ? `${queryColumnRef(sortCol.value)} ${sortDir.value.toUpperCase()}` : undefined)
);
}
@@ -1313,7 +1313,7 @@ type FilterMode =
function contextFilterCondition(mode: FilterMode): string | null {
if (!contextColumn.value) return null;
const column = quoteIdent(contextColumn.value);
const column = queryColumnRef(contextColumn.value);
const value = contextCellValue.value;
if (mode === "is-null") return `${column} IS NULL`;
@@ -1355,6 +1355,7 @@ async function applyOrderBySearch() {
databaseType: props.databaseType,
schema: props.tableMeta.schema,
tableName: props.tableMeta.tableName,
columns: props.tableMeta.columns.map((column) => column.name),
primaryKeys: props.tableMeta.primaryKeys,
orderBy: orderByClause,
limit: pageSize.value,
@@ -1379,10 +1380,11 @@ async function applyWhereFilter() {
databaseType: props.databaseType,
schema: props.tableMeta.schema,
tableName: props.tableMeta.tableName,
columns: props.tableMeta.columns.map((column) => column.name),
primaryKeys: props.tableMeta.primaryKeys,
orderBy:
orderByInput.value.trim() ||
(sortCol.value ? `${quoteIdent(sortCol.value)} ${sortDir.value.toUpperCase()}` : undefined),
(sortCol.value ? `${queryColumnRef(sortCol.value)} ${sortDir.value.toUpperCase()}` : undefined),
limit: pageSize.value,
whereInput: whereFilterInput.value.trim() || undefined,
includeRowId: tableUsesSyntheticRowId.value,
@@ -1408,6 +1410,11 @@ function quoteIdent(name: string): string {
return quoteTableIdentifier(props.databaseType, name);
}
function queryColumnRef(name: string): string {
const quoted = quoteIdent(name);
return props.databaseType === "neo4j" ? `n.${quoted}` : quoted;
}
function escapeVal(value: CellValue): string {
return formatGridSqlLiteral(value);
}
+10 -2
View File
@@ -31,7 +31,7 @@ import DangerConfirmDialog from "@/components/editor/DangerConfirmDialog.vue";
import * as api from "@/lib/api";
import type { ConnectionConfig, ObjectInfo, ObjectSourceKind } from "@/types/database";
import { isSchemaAware } from "@/lib/databaseCapabilities";
import { qualifiedTableName } from "@/lib/tableSelectSql";
import { buildTableSelectSql, qualifiedTableName } from "@/lib/tableSelectSql";
import { useToast } from "@/composables/useToast";
import { buildExecutableObjectSourceSql, objectSourceSaveExecutionMode } from "@/lib/objectSourceEditor";
import { useQueryStore } from "@/stores/queryStore";
@@ -215,7 +215,15 @@ async function openSource(row: ObjectRow) {
function openNewQuery(row: ObjectRow) {
const tabId = queryStore.createTab(props.connection.id, props.database, row.name);
queryStore.updateSql(tabId, `SELECT * FROM ${qualifiedName(row)} LIMIT 100;`);
queryStore.updateSql(
tabId,
buildTableSelectSql({
databaseType: props.connection.db_type,
schema: row.schema || selectedSchema.value,
tableName: row.name,
limit: 100,
}),
);
}
function qualifiedName(row: ObjectRow): string {
+29 -6
View File
@@ -415,6 +415,7 @@ async function openData() {
databaseType: config.db_type,
schema: node.schema,
tableName: node.label,
columns: columns.map((column) => column.name),
primaryKeys: pks,
includeRowId: usesSyntheticRowIdKey(config.db_type, pks),
});
@@ -896,7 +897,20 @@ async function exportData(format: "csv" | "json" | "sql") {
isSchemaAware(config.db_type) && node.schema
? `${quoteIdent(node.schema)}.${quoteIdent(node.label)}`
: quoteIdent(node.label);
const result = await api.executeQuery(node.connectionId, node.database, `SELECT * FROM ${qualifiedName}`);
const queryColumns =
config.db_type === "neo4j"
? (await api.getColumns(node.connectionId, node.database, node.schema || node.database, node.label)).map(
(column) => column.name,
)
: undefined;
const dataSql = buildTableSelectSql({
databaseType: config.db_type,
schema: node.schema,
tableName: node.label,
columns: queryColumns,
limit: 10000,
});
const result = await api.executeQuery(node.connectionId, node.database, dataSql);
let content: string;
let ext: string;
@@ -927,11 +941,20 @@ async function exportDataXlsx() {
try {
await connectionStore.ensureConnected(node.connectionId);
const qualifiedName =
isSchemaAware(config.db_type) && node.schema
? `${quoteIdent(node.schema)}.${quoteIdent(node.label)}`
: quoteIdent(node.label);
const result = await api.executeQuery(node.connectionId, node.database, `SELECT * FROM ${qualifiedName}`);
const queryColumns =
config.db_type === "neo4j"
? (await api.getColumns(node.connectionId, node.database, node.schema || node.database, node.label)).map(
(column) => column.name,
)
: undefined;
const dataSql = buildTableSelectSql({
databaseType: config.db_type,
schema: node.schema,
tableName: node.label,
columns: queryColumns,
limit: 10000,
});
const result = await api.executeQuery(node.connectionId, node.database, dataSql);
const { buildXlsxWorkbook } = await import("@/lib/xlsxExport");
const workbook = buildXlsxWorkbook({