feat(grid): edit Oracle join query results via ROWID
This commit is contained in:
4 files changed
+110
-9
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildQueryWithHiddenPrimaryKeys, hiddenResultColumnIndexes } from "@/lib/sql/editableQueryHiddenKeys";
|
||||
import { analyzeEditableQueryEditability, sourceColumnsForResult } from "@/lib/sql/sqlAnalysis";
|
||||
import { analyzeEditableQueryEditability, allPrimaryKeysPresent, sourceColumnsForResult, type EditableQueryInfo } from "@/lib/sql/sqlAnalysis";
|
||||
|
||||
describe("editable query hidden primary keys", () => {
|
||||
it("appends quoted MySQL primary keys without changing the visible projection", () => {
|
||||
@@ -216,6 +216,35 @@ describe("editable query hidden primary keys", () => {
|
||||
expect(analyzeEditableQueryEditability("select id from jobs union select id from archived_jobs")).toEqual({ editable: false, reason: "set-operation" });
|
||||
});
|
||||
|
||||
it("maps a qualified Oracle ROWID projection to the synthetic row key", () => {
|
||||
const analysis: EditableQueryInfo = {
|
||||
schema: "APP",
|
||||
tableName: "USERS",
|
||||
selectStar: false,
|
||||
columns: [
|
||||
{ sourceName: "ROWID", sourceQualifier: "t", sourceKey: "t:0", resultName: "ROWID", expression: "t.ROWID" },
|
||||
{ sourceName: "NAME", sourceQualifier: "t", sourceKey: "t:0", resultName: "NAME", expression: "t.NAME" },
|
||||
{ sourceName: "LABEL", sourceQualifier: "o", sourceKey: "o:1", resultName: "LABEL", expression: "o.LABEL" },
|
||||
],
|
||||
};
|
||||
|
||||
expect(allPrimaryKeysPresent(["__DBX_ROWID"], ["ROWID", "NAME", "LABEL"], analysis, "t:0", "oracle")).toBe(true);
|
||||
expect(sourceColumnsForResult(analysis, ["ROWID", "NAME", "LABEL"], "t:0", "oracle", ["__DBX_ROWID"])).toEqual(["__DBX_ROWID", "NAME", undefined]);
|
||||
expect(allPrimaryKeysPresent(["__DBX_ROWID"], ["ROWID", "NAME", "LABEL"], analysis, "o:1", "oracle")).toBe(false);
|
||||
});
|
||||
|
||||
it("does not assign an unqualified multi-source ROWID to a target table", () => {
|
||||
const analysis: EditableQueryInfo = {
|
||||
schema: "APP",
|
||||
tableName: "USERS",
|
||||
selectStar: false,
|
||||
columns: [{ sourceName: "ROWID", resultName: "ROWID", expression: "ROWID" }],
|
||||
};
|
||||
|
||||
expect(allPrimaryKeysPresent(["__DBX_ROWID"], ["ROWID"], analysis, "t:0", "oracle")).toBe(false);
|
||||
expect(sourceColumnsForResult(analysis, ["ROWID"], "t:0", "oracle", ["__DBX_ROWID"])).toEqual([undefined]);
|
||||
});
|
||||
|
||||
it("resolves appended aliases to result indexes", () => {
|
||||
expect(
|
||||
hiddenResultColumnIndexes(
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import type { DatabaseType } from "@/types/database";
|
||||
import { DBX_ROWID_COLUMN } from "@/lib/table/tableEditing";
|
||||
|
||||
// Binary column types that should not be edited inline
|
||||
export const BINARY_TYPES = new Set(["blob", "clob", "bytea", "varbinary", "binary", "image", "longblob", "mediumblob", "tinyblob", "blob sub_type 2004", "blob sub_type 2005"]);
|
||||
|
||||
@@ -812,12 +815,13 @@ function escapeRegExp(value: string): string {
|
||||
* comparison prevents `id` from being mistaken for a distinct quoted `"ID"`
|
||||
* column in PostgreSQL.
|
||||
*/
|
||||
export function allPrimaryKeysPresent(primaryKeys: string[], resultColumns: string[], analysis?: EditableQueryInfo, sourceKey?: string): boolean {
|
||||
export function allPrimaryKeysPresent(primaryKeys: string[], resultColumns: string[], analysis?: EditableQueryInfo, sourceKey?: string, databaseType?: DatabaseType): boolean {
|
||||
if (analysis && !analysis.selectStar) {
|
||||
const sourceColumns = new Set(
|
||||
analysis.columns.flatMap((column) => {
|
||||
if (!column.sourceName) return [];
|
||||
if (sourceKey && column.sourceKey !== sourceKey) return [];
|
||||
if (databaseType === "oracle" && !column.sourceNameQuoted && column.sourceName.toUpperCase() === "ROWID" && column.sourceKey === sourceKey) return [DBX_ROWID_COLUMN, column.sourceName];
|
||||
return [column.sourceName];
|
||||
}),
|
||||
);
|
||||
@@ -850,12 +854,15 @@ export function allEditableColumnsWriteable(analysis: EditableQueryInfo, resultC
|
||||
return !!matchedColumns && matchedColumns.every((source) => !sourceKey || !source.sourceName || source.sourceKey === sourceKey);
|
||||
}
|
||||
|
||||
export function sourceColumnsForResult(analysis: EditableQueryInfo, resultColumns: string[], sourceKey?: string): Array<string | undefined> | undefined {
|
||||
export function sourceColumnsForResult(analysis: EditableQueryInfo, resultColumns: string[], sourceKey?: string, databaseType?: DatabaseType, primaryKeys?: readonly string[]): Array<string | undefined> | undefined {
|
||||
if (analysis.selectStar) return undefined;
|
||||
const matchedColumns = matchColumnsForResult(analysis, resultColumns);
|
||||
if (!matchedColumns) return undefined;
|
||||
return matchedColumns.map((column) => {
|
||||
if (sourceKey && column.sourceKey !== sourceKey) return undefined;
|
||||
if (databaseType === "oracle" && !column.sourceNameQuoted && column.sourceName?.toUpperCase() === "ROWID" && column.sourceKey === sourceKey) {
|
||||
return primaryKeys?.length === 1 && primaryKeys[0] === DBX_ROWID_COLUMN ? DBX_ROWID_COLUMN : undefined;
|
||||
}
|
||||
return column.sourceName;
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user