feat(query): support editing without selected primary keys
This commit is contained in:
11 files changed
+935
-88
No files matched your search
@@ -22,6 +22,7 @@ export interface EditableQueryInfo {
|
||||
sources?: EditableQuerySource[];
|
||||
editableSourceKey?: string;
|
||||
multiSource?: boolean;
|
||||
allowInsert?: boolean;
|
||||
allowInsertDelete?: boolean;
|
||||
distinct?: boolean;
|
||||
}
|
||||
@@ -83,10 +84,11 @@ export function analyzeEditableQueryEditability(sql: string): QueryEditability {
|
||||
|
||||
const rawSelectBody = normalized.slice("SELECT".length, fromIndex).trim();
|
||||
const distinct = /^DISTINCT\b/i.test(rawSelectBody);
|
||||
const selectBody = distinct ? rawSelectBody.replace(/^DISTINCT\b/i, "").trimStart() : rawSelectBody;
|
||||
const selectBodyWithoutDistinct = distinct ? rawSelectBody.replace(/^DISTINCT\b/i, "").trimStart() : rawSelectBody;
|
||||
// DISTINCT ON selects a representative row using database-specific ordering,
|
||||
// so it cannot be mapped to base rows like an ordinary DISTINCT projection.
|
||||
if (distinct && /^ON\b/i.test(selectBody)) return { editable: false, reason: "aggregation" };
|
||||
if (distinct && /^ON\b/i.test(selectBodyWithoutDistinct)) return { editable: false, reason: "aggregation" };
|
||||
const selectBody = stripSqlServerTopClause(selectBodyWithoutDistinct);
|
||||
|
||||
const groupIndex = findTopLevelKeyword(normalized, "GROUP", fromIndex + 4);
|
||||
const havingIndex = findTopLevelKeyword(normalized, "HAVING", fromIndex + 4);
|
||||
@@ -133,6 +135,14 @@ export function queryEditabilityMessageKey(reason: QueryEditabilityReason): stri
|
||||
return `grid.queryEditUnsupported.${reason}`;
|
||||
}
|
||||
|
||||
function stripSqlServerTopClause(body: string): string {
|
||||
const topMatch = body.match(/^TOP(?:\s+|(?=\())(?:\((?:[^()'"`[\]]|"[^"]*"|'(?:''|[^'])*'|`[^`]*`|\[[^\]]*\])+\)|\d+)\s*/i);
|
||||
if (!topMatch) return body;
|
||||
let remaining = body.slice(topMatch[0].length).trimStart();
|
||||
remaining = remaining.replace(/^PERCENT\b\s*/i, "").replace(/^WITH\s+TIES\b\s*/i, "");
|
||||
return remaining || body;
|
||||
}
|
||||
|
||||
function parseSelectColumns(body: string, sources?: EditableQuerySource[]): EditableQueryColumn[] {
|
||||
const cols: EditableQueryColumn[] = [];
|
||||
let depth = 0;
|
||||
|
||||
Reference in new issue
Block a user