Skip to content

Commit 7780403

Browse files
authored
Add support for sql queries in editor and repl (#377)
* Add support for sql queries in editor and repl * Add `\clear` command in repl * Always show repl input mode + render mode in different colour
1 parent e2baa2b commit 7780403

File tree

23 files changed

+837
-159
lines changed

23 files changed

+837
-159
lines changed

shared/codeEditor/index.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,15 @@ export function createCodeEditor({
221221
language,
222222
highlightActiveLine = true,
223223
formatLineNo,
224+
disableLineNumbers,
224225
terminalCursor,
225226
customExtensions = [],
226227
showIndentationMarkers = true,
227228
}: {
228229
language?: LanguageSupport | null;
229230
highlightActiveLine?: boolean;
230231
formatLineNo?: (lineNo: number) => string;
232+
disableLineNumbers?: boolean;
231233
terminalCursor?: boolean;
232234
customExtensions?: Extension;
233235
showIndentationMarkers?: boolean;
@@ -266,9 +268,11 @@ export function createCodeEditor({
266268
})
267269
),
268270
highlightActiveLine ? highlightActiveLineExt() : [],
269-
lineNumbers({
270-
formatNumber: formatLineNo,
271-
}),
271+
!disableLineNumbers
272+
? lineNumbers({
273+
formatNumber: formatLineNo,
274+
})
275+
: [],
272276
readOnlyComp.of([
273277
EditorState.readOnly.of(readonly),
274278
EditorView.editable.of(!readonly),

shared/common/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.0.0",
44
"private": true,
55
"peerDependencies": {
6-
"edgedb": "1.6.0-canary.20241030T172506",
6+
"edgedb": "1.6.0-canary.20241126T162412",
77
"react": "^18.0.0",
88
"react-dom": "^18.0.0"
99
},

shared/common/schemaData/knownTypes.ts

+6
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,10 @@ export const KnownScalarTypes = [
2727
"ext::pgvector::vector",
2828
"ext::pgvector::halfvec",
2929
"ext::pgvector::sparsevec",
30+
31+
"std::pg::json",
32+
"std::pg::timestamptz",
33+
"std::pg::timestamp",
34+
"std::pg::date",
35+
"std::pg::interval",
3036
] as const;

shared/inspector/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"version": "0.0.0",
55
"license": "UNLICENSED",
66
"peerDependencies": {
7-
"edgedb": "1.6.0-canary.20241030T172506",
7+
"edgedb": "1.6.0-canary.20241126T162412",
88
"react": "^18.0.0",
99
"react-dom": "^18.0.0"
1010
},

shared/schemaGraph/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"version": "0.0.0",
55
"license": "UNLICENSED",
66
"peerDependencies": {
7-
"edgedb": "1.6.0-canary.20241030T172506",
7+
"edgedb": "1.6.0-canary.20241126T162412",
88
"react": "^18.0.0",
99
"react-dom": "^18.0.0"
1010
},

shared/studio/components/dataEditor/utils.ts

+107
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ export interface EditorArrayType {
1212
elementType: PrimitiveType;
1313
}
1414

15+
export interface SerializedEditorArrayType
16+
extends Omit<EditorArrayType, "elementType"> {
17+
elementType: SerializedPrimitiveType;
18+
}
19+
1520
export interface EditorTupleType {
1621
schemaType: "Tuple";
1722
name: string;
@@ -22,25 +27,127 @@ export interface EditorTupleType {
2227
}[];
2328
}
2429

30+
export interface SerializedEditorTupleType
31+
extends Omit<EditorTupleType, "elements"> {
32+
elements: {
33+
name: string | null;
34+
type: SerializedPrimitiveType;
35+
}[];
36+
}
37+
2538
export interface EditorRangeType {
2639
schemaType: "Range";
2740
name: string;
2841
elementType: SchemaScalarType;
2942
}
3043

44+
export interface SerializedEditorRangeType
45+
extends Omit<EditorRangeType, "elementType"> {
46+
elementType: string;
47+
}
48+
3149
export interface EditorMultirangeType {
3250
schemaType: "Multirange";
3351
name: string;
3452
rangeType: EditorRangeType;
3553
}
3654

55+
export interface SerializedEditorMultirangeType
56+
extends Omit<EditorMultirangeType, "rangeType"> {
57+
rangeType: SerializedEditorRangeType;
58+
}
59+
3760
export type PrimitiveType =
3861
| SchemaScalarType
3962
| EditorRangeType
4063
| EditorMultirangeType
4164
| EditorArrayType
4265
| EditorTupleType;
4366

67+
export type SerializedPrimitiveType =
68+
| string
69+
| SerializedEditorRangeType
70+
| SerializedEditorMultirangeType
71+
| SerializedEditorArrayType
72+
| SerializedEditorTupleType;
73+
74+
export function serializePrimitiveType(
75+
type: PrimitiveType
76+
): SerializedPrimitiveType {
77+
switch (type.schemaType) {
78+
case "Scalar":
79+
return type.name;
80+
case "Array":
81+
return {...type, elementType: serializePrimitiveType(type.elementType)};
82+
case "Tuple":
83+
return {
84+
...type,
85+
elements: type.elements.map((el) => ({
86+
...el,
87+
type: serializePrimitiveType(el.type),
88+
})),
89+
};
90+
case "Range":
91+
return {...type, elementType: type.elementType.name};
92+
case "Multirange":
93+
return {
94+
...type,
95+
rangeType: serializePrimitiveType(
96+
type.rangeType
97+
) as SerializedEditorRangeType,
98+
};
99+
default:
100+
assertNever(type);
101+
}
102+
}
103+
104+
export function deserializePrimitiveType(
105+
type: SerializedPrimitiveType,
106+
schemaScalars: Map<string, SchemaScalarType>
107+
): PrimitiveType {
108+
if (typeof type === "string") {
109+
const scalar = schemaScalars.get(type);
110+
if (!scalar)
111+
throw new Error(
112+
`failed to deserialize primitive type: could not find schema type for scalar '${type}'`
113+
);
114+
return scalar;
115+
}
116+
switch (type.schemaType) {
117+
case "Array":
118+
return {
119+
...type,
120+
elementType: deserializePrimitiveType(type.elementType, schemaScalars),
121+
};
122+
case "Tuple":
123+
return {
124+
...type,
125+
elements: type.elements.map((el) => ({
126+
...el,
127+
type: deserializePrimitiveType(el.type, schemaScalars),
128+
})),
129+
};
130+
case "Range":
131+
return {
132+
...type,
133+
elementType: deserializePrimitiveType(
134+
type.elementType,
135+
schemaScalars
136+
) as SchemaScalarType,
137+
};
138+
case "Multirange":
139+
return {
140+
...type,
141+
rangeType: deserializePrimitiveType(
142+
type.rangeType,
143+
schemaScalars
144+
) as EditorRangeType,
145+
};
146+
default:
147+
assertNever(type);
148+
}
149+
}
150+
44151
export interface EditorRangeValue {
45152
lower: string | null;
46153
upper: string | null;

shared/studio/idbStore/index.ts

+37
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,35 @@ async function _fetchHistory(
179179
return items;
180180
}
181181

182+
async function _clearHistory(
183+
storeId: "queryHistory" | "replHistory",
184+
instanceId: string,
185+
dbName: string,
186+
getResultDataId: (item: QueryHistoryItem) => string | null
187+
) {
188+
const tx = (await db).transaction([storeId, "queryResultData"], "readwrite");
189+
let cursor = await tx
190+
.objectStore(storeId)
191+
.openCursor(
192+
IDBKeyRange.bound(
193+
[instanceId, dbName, -Infinity],
194+
[instanceId, dbName, Infinity]
195+
)
196+
);
197+
const deletes: Promise<any>[] = [];
198+
while (cursor) {
199+
const currentItem = cursor;
200+
const resultDataId = getResultDataId(currentItem.value);
201+
if (resultDataId) {
202+
deletes.push(tx.objectStore("queryResultData").delete(resultDataId));
203+
}
204+
deletes.push(currentItem.delete());
205+
cursor = await cursor.continue();
206+
}
207+
deletes.push(tx.done);
208+
return await Promise.all(deletes);
209+
}
210+
182211
export function fetchQueryHistory(
183212
instanceId: string,
184213
dbName: string,
@@ -209,6 +238,14 @@ export function fetchReplHistory(
209238
);
210239
}
211240

241+
export function clearReplHistory(
242+
instanceId: string,
243+
dbName: string,
244+
getResultDataId: (item: QueryHistoryItem) => string | null
245+
) {
246+
return _clearHistory("replHistory", instanceId, dbName, getResultDataId);
247+
}
248+
212249
export async function fetchResultData(itemId: string) {
213250
return (await db).get("queryResultData", itemId);
214251
}

shared/studio/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"dependencies": {
66
"@anthropic-ai/sdk": "^0.20.5",
77
"@codemirror/lang-json": "^6.0.0",
8+
"@codemirror/lang-sql": "^6.8.0",
89
"@codemirror/lint": "^6.0.0",
910
"@edgedb/code-editor": "workspace:*",
1011
"@edgedb/common": "workspace:*",
@@ -28,7 +29,7 @@
2829
"react-window": "^1.8.10"
2930
},
3031
"peerDependencies": {
31-
"edgedb": "1.6.0-canary.20241030T172506",
32+
"edgedb": "1.6.0-canary.20241126T162412",
3233
"react": "^18.0.0",
3334
"react-dom": "^18.0.0"
3435
},

0 commit comments

Comments
 (0)