Skip to content

Commit 6031ec8

Browse files
authored
fix(explorer): validate sql queries (#3793)
1 parent 062bd8d commit 6031ec8

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

.changeset/poor-pianos-retire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@latticexyz/explorer": patch
3+
---
4+
5+
SQL queries in the tables viewer are now validated before execution, with errors highlighted and described directly in the editor.

packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/explore/SQLEditor.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ export function SQLEditor({ table, isLiveQuery, setIsLiveQuery }: Props) {
7676
form.reset({ query });
7777
}, [query, form]);
7878

79+
useEffect(() => {
80+
if (editorRef.current) {
81+
editorRef.current.addAction({
82+
id: "executeSQL",
83+
label: "Execute SQL command",
84+
keybindings: [KeyMod.CtrlCmd | KeyCode.Enter],
85+
run: () => handleSubmit(),
86+
});
87+
}
88+
}, [handleSubmit]);
89+
7990
const updateHeight = () => {
8091
if (editorRef.current) {
8192
const contentHeight = Math.min(200, editorRef.current.getContentHeight());
@@ -121,13 +132,6 @@ export function SQLEditor({ table, isLiveQuery, setIsLiveQuery }: Props) {
121132
});
122133
monaco.editor.setTheme("custom-vs-dark");
123134

124-
editor.addAction({
125-
id: "executeSQL",
126-
label: "Execute SQL command",
127-
keybindings: [KeyMod.CtrlCmd | KeyCode.Enter],
128-
run: () => handleSubmit(),
129-
});
130-
131135
updateHeight();
132136
editor.onDidContentSizeChange(updateHeight);
133137
editor.onDidFocusEditorText(() => setIsFocused(true));

packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/explore/utils/getLimitOffset.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,32 @@ const opt = {
66
};
77

88
export function getLimitOffset(query: string) {
9-
const decodedQuery = decodeURIComponent(query);
10-
let ast = sqlParser.astify(decodedQuery, opt);
11-
if (Array.isArray(ast) && ast.length > 0) {
12-
const astFirst = ast[0];
13-
if (astFirst) {
14-
ast = astFirst;
9+
try {
10+
const decodedQuery = decodeURIComponent(query);
11+
let ast = sqlParser.astify(decodedQuery, opt);
12+
if (Array.isArray(ast) && ast.length > 0) {
13+
const astFirst = ast[0];
14+
if (astFirst) {
15+
ast = astFirst;
16+
}
1517
}
16-
}
1718

18-
let limit = null;
19-
let offset = null;
19+
let limit = null;
20+
let offset = null;
2021

21-
if ("limit" in ast) {
22-
// If limit has a separator "offset", it contains both limit and offset values. Otherwise, only limit is set.
23-
if (ast.limit?.seperator === "offset") {
24-
limit = ast.limit?.value?.[0]?.value;
25-
offset = ast.limit?.value?.[1]?.value;
26-
} else {
27-
limit = ast.limit?.value?.[0]?.value;
22+
if ("limit" in ast) {
23+
// If limit has a separator "offset", it contains both limit and offset values. Otherwise, only limit is set.
24+
if (ast.limit?.seperator === "offset") {
25+
limit = ast.limit?.value?.[0]?.value;
26+
offset = ast.limit?.value?.[1]?.value;
27+
} else {
28+
limit = ast.limit?.value?.[0]?.value;
29+
}
2830
}
29-
}
3031

31-
return { limit, offset };
32+
return { limit, offset };
33+
} catch (error) {
34+
console.error("Error parsing query:", error);
35+
return { limit: null, offset: null };
36+
}
3237
}

0 commit comments

Comments
 (0)