Skip to content

Commit

Permalink
Add support for sql queries in editor and repl (#377)
Browse files Browse the repository at this point in the history
* Add support for sql queries in editor and repl

* Add `\clear` command in repl

* Always show repl input mode + render mode in different colour
  • Loading branch information
jaclarke authored Nov 26, 2024
1 parent e2baa2b commit 7780403
Show file tree
Hide file tree
Showing 23 changed files with 837 additions and 159 deletions.
10 changes: 7 additions & 3 deletions shared/codeEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,15 @@ export function createCodeEditor({
language,
highlightActiveLine = true,
formatLineNo,
disableLineNumbers,
terminalCursor,
customExtensions = [],
showIndentationMarkers = true,
}: {
language?: LanguageSupport | null;
highlightActiveLine?: boolean;
formatLineNo?: (lineNo: number) => string;
disableLineNumbers?: boolean;
terminalCursor?: boolean;
customExtensions?: Extension;
showIndentationMarkers?: boolean;
Expand Down Expand Up @@ -266,9 +268,11 @@ export function createCodeEditor({
})
),
highlightActiveLine ? highlightActiveLineExt() : [],
lineNumbers({
formatNumber: formatLineNo,
}),
!disableLineNumbers
? lineNumbers({
formatNumber: formatLineNo,
})
: [],
readOnlyComp.of([
EditorState.readOnly.of(readonly),
EditorView.editable.of(!readonly),
Expand Down
2 changes: 1 addition & 1 deletion shared/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"private": true,
"peerDependencies": {
"edgedb": "1.6.0-canary.20241030T172506",
"edgedb": "1.6.0-canary.20241126T162412",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
Expand Down
6 changes: 6 additions & 0 deletions shared/common/schemaData/knownTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,10 @@ export const KnownScalarTypes = [
"ext::pgvector::vector",
"ext::pgvector::halfvec",
"ext::pgvector::sparsevec",

"std::pg::json",
"std::pg::timestamptz",
"std::pg::timestamp",
"std::pg::date",
"std::pg::interval",
] as const;
2 changes: 1 addition & 1 deletion shared/inspector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.0",
"license": "UNLICENSED",
"peerDependencies": {
"edgedb": "1.6.0-canary.20241030T172506",
"edgedb": "1.6.0-canary.20241126T162412",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
Expand Down
2 changes: 1 addition & 1 deletion shared/schemaGraph/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.0",
"license": "UNLICENSED",
"peerDependencies": {
"edgedb": "1.6.0-canary.20241030T172506",
"edgedb": "1.6.0-canary.20241126T162412",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
Expand Down
107 changes: 107 additions & 0 deletions shared/studio/components/dataEditor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export interface EditorArrayType {
elementType: PrimitiveType;
}

export interface SerializedEditorArrayType
extends Omit<EditorArrayType, "elementType"> {
elementType: SerializedPrimitiveType;
}

export interface EditorTupleType {
schemaType: "Tuple";
name: string;
Expand All @@ -22,25 +27,127 @@ export interface EditorTupleType {
}[];
}

export interface SerializedEditorTupleType
extends Omit<EditorTupleType, "elements"> {
elements: {
name: string | null;
type: SerializedPrimitiveType;
}[];
}

export interface EditorRangeType {
schemaType: "Range";
name: string;
elementType: SchemaScalarType;
}

export interface SerializedEditorRangeType
extends Omit<EditorRangeType, "elementType"> {
elementType: string;
}

export interface EditorMultirangeType {
schemaType: "Multirange";
name: string;
rangeType: EditorRangeType;
}

export interface SerializedEditorMultirangeType
extends Omit<EditorMultirangeType, "rangeType"> {
rangeType: SerializedEditorRangeType;
}

export type PrimitiveType =
| SchemaScalarType
| EditorRangeType
| EditorMultirangeType
| EditorArrayType
| EditorTupleType;

export type SerializedPrimitiveType =
| string
| SerializedEditorRangeType
| SerializedEditorMultirangeType
| SerializedEditorArrayType
| SerializedEditorTupleType;

export function serializePrimitiveType(
type: PrimitiveType
): SerializedPrimitiveType {
switch (type.schemaType) {
case "Scalar":
return type.name;
case "Array":
return {...type, elementType: serializePrimitiveType(type.elementType)};
case "Tuple":
return {
...type,
elements: type.elements.map((el) => ({
...el,
type: serializePrimitiveType(el.type),
})),
};
case "Range":
return {...type, elementType: type.elementType.name};
case "Multirange":
return {
...type,
rangeType: serializePrimitiveType(
type.rangeType
) as SerializedEditorRangeType,
};
default:
assertNever(type);
}
}

export function deserializePrimitiveType(
type: SerializedPrimitiveType,
schemaScalars: Map<string, SchemaScalarType>
): PrimitiveType {
if (typeof type === "string") {
const scalar = schemaScalars.get(type);
if (!scalar)
throw new Error(
`failed to deserialize primitive type: could not find schema type for scalar '${type}'`
);
return scalar;
}
switch (type.schemaType) {
case "Array":
return {
...type,
elementType: deserializePrimitiveType(type.elementType, schemaScalars),
};
case "Tuple":
return {
...type,
elements: type.elements.map((el) => ({
...el,
type: deserializePrimitiveType(el.type, schemaScalars),
})),
};
case "Range":
return {
...type,
elementType: deserializePrimitiveType(
type.elementType,
schemaScalars
) as SchemaScalarType,
};
case "Multirange":
return {
...type,
rangeType: deserializePrimitiveType(
type.rangeType,
schemaScalars
) as EditorRangeType,
};
default:
assertNever(type);
}
}

export interface EditorRangeValue {
lower: string | null;
upper: string | null;
Expand Down
37 changes: 37 additions & 0 deletions shared/studio/idbStore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,35 @@ async function _fetchHistory(
return items;
}

async function _clearHistory(
storeId: "queryHistory" | "replHistory",
instanceId: string,
dbName: string,
getResultDataId: (item: QueryHistoryItem) => string | null
) {
const tx = (await db).transaction([storeId, "queryResultData"], "readwrite");
let cursor = await tx
.objectStore(storeId)
.openCursor(
IDBKeyRange.bound(
[instanceId, dbName, -Infinity],
[instanceId, dbName, Infinity]
)
);
const deletes: Promise<any>[] = [];
while (cursor) {
const currentItem = cursor;
const resultDataId = getResultDataId(currentItem.value);
if (resultDataId) {
deletes.push(tx.objectStore("queryResultData").delete(resultDataId));
}
deletes.push(currentItem.delete());
cursor = await cursor.continue();
}
deletes.push(tx.done);
return await Promise.all(deletes);
}

export function fetchQueryHistory(
instanceId: string,
dbName: string,
Expand Down Expand Up @@ -209,6 +238,14 @@ export function fetchReplHistory(
);
}

export function clearReplHistory(
instanceId: string,
dbName: string,
getResultDataId: (item: QueryHistoryItem) => string | null
) {
return _clearHistory("replHistory", instanceId, dbName, getResultDataId);
}

export async function fetchResultData(itemId: string) {
return (await db).get("queryResultData", itemId);
}
Expand Down
3 changes: 2 additions & 1 deletion shared/studio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dependencies": {
"@anthropic-ai/sdk": "^0.20.5",
"@codemirror/lang-json": "^6.0.0",
"@codemirror/lang-sql": "^6.8.0",
"@codemirror/lint": "^6.0.0",
"@edgedb/code-editor": "workspace:*",
"@edgedb/common": "workspace:*",
Expand All @@ -28,7 +29,7 @@
"react-window": "^1.8.10"
},
"peerDependencies": {
"edgedb": "1.6.0-canary.20241030T172506",
"edgedb": "1.6.0-canary.20241126T162412",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
Expand Down
Loading

0 comments on commit 7780403

Please sign in to comment.