Skip to content

Commit

Permalink
Add hint to quote table names for sql 'unknown table' errors (#410)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaclarke authored Feb 21, 2025
1 parent 9b6a6b9 commit 7a01bab
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 7 deletions.
10 changes: 6 additions & 4 deletions shared/studio/tabs/queryEditor/state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,8 @@ export class QueryEditor extends Model({
.activeState.options.find((opt) => opt.name === "Implicit Limit")
?.value as bigint | undefined;

const lang =
this.selectedEditor === EditorKind.SQL ? Language.SQL : Language.EDGEQL;
try {
const {result, outCodecBuf, resultBuf, protoVer, capabilities, status} =
yield* _await(
Expand All @@ -794,9 +796,7 @@ export class QueryEditor extends Model({
replQueryTag: true,
},
this.runningQueryAbort?.signal,
this.selectedEditor === EditorKind.SQL
? Language.SQL
: Language.EDGEQL
lang
)
);

Expand All @@ -819,7 +819,9 @@ export class QueryEditor extends Model({
queryData,
timestamp,
thumbnailData,
error: extractErrorDetails(e, query),
error: extractErrorDetails(e, query, lang, () => [
...(dbCtx.get(this)?.schemaData?.objectsByName.keys() ?? []),
]),
});
}
return {success: false};
Expand Down
10 changes: 8 additions & 2 deletions shared/studio/tabs/repl/state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@ export class Repl extends Model({

dbState.setLoadingTab(Repl, true);

const lang =
this.language === ReplLang.SQL ? Language.SQL : Language.EDGEQL;
let resultData: QueryResultData | undefined = undefined;
let skipStoreHistoryItem = false;
try {
Expand Down Expand Up @@ -500,7 +502,7 @@ export class Repl extends Model({
replQueryTag: true,
},
(this._runningQuery as AbortController).signal,
this.language === ReplLang.SQL ? Language.SQL : Language.EDGEQL
lang
)
);

Expand Down Expand Up @@ -542,7 +544,11 @@ export class Repl extends Model({
}
}
} catch (err: any) {
historyItem.setError(extractErrorDetails(err, query));
historyItem.setError(
extractErrorDetails(err, query, lang, () => [
...(dbCtx.get(this)?.schemaData?.objectsByName.keys() ?? []),
])
);
}

if (!skipStoreHistoryItem) {
Expand Down
41 changes: 40 additions & 1 deletion shared/studio/utils/extractErrorDetails.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {EdgeDBError} from "edgedb";
import {Language} from "edgedb/dist/ifaces";
import {utf8Decoder} from "edgedb/dist/primitives/buffer";

enum ErrorField {
Expand Down Expand Up @@ -33,7 +34,12 @@ function tryParseInt(val: any) {
return null;
}

export function extractErrorDetails(err: any, query?: string): ErrorDetails {
export function extractErrorDetails(
err: any,
query?: string,
lang?: Language,
getObjectTypeNames?: () => string[]
): ErrorDetails {
if (!(err instanceof Error)) {
throw new Error(`Fatal Error: cannot handle non error as error: ${err}`);
}
Expand Down Expand Up @@ -87,5 +93,38 @@ export function extractErrorDetails(err: any, query?: string): ErrorDetails {
}
}

if (lang === Language.SQL && !errDetails.hint && getObjectTypeNames) {
const match = errDetails.msg.match(/unknown table `(.*)`/);
if (match) {
const name = match[1];
const typeNames = getObjectTypeNames();
if (
name.startsWith('"') &&
name.endsWith('"') &&
typeNames.includes(name.slice(1, -1))
) {
errDetails.hint = `Try specifying the module name using SQL syntax: ${name
.slice(1, -1)
.split("::")
.map((part) => (part.toLowerCase() === part ? part : `"${part}"`))
.join(".")}`;
} else {
const colonised = name.replace(".", "::");
for (const typeName of typeNames) {
const stripped = typeName.replace(/^default::/, "");
if (stripped.toLowerCase() === colonised) {
errDetails.hint = `Try quoting the table name: ${stripped
.split("::")
.map((part) =>
part.toLowerCase() === part ? part : `"${part}"`
)
.join(".")}`;
break;
}
}
}
}
}

return errDetails;
}

0 comments on commit 7a01bab

Please sign in to comment.