Skip to content

Commit

Permalink
Add named queries
Browse files Browse the repository at this point in the history
  • Loading branch information
Will Scullin committed Sep 1, 2023
1 parent fa74032 commit 23e82d9
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 27 deletions.
6 changes: 6 additions & 0 deletions src/common/message_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import {
MalloyError,
MalloyQueryData,
NamedQuery,
ResultJSON,
SerializedExplore,
} from '@malloydata/malloy';
Expand Down Expand Up @@ -365,3 +366,8 @@ export type HelpPanelMessage = HelpMessageAppReady | HelpMessageEditConnections;
export const queryPanelProgress = new ProgressType<QueryMessageStatus>();

export const msqlPanelProgress = new ProgressType<MSQLMessageStatus>();

export interface FetchModelMessage {
explores: SerializedExplore[];
queries: NamedQuery[];
}
10 changes: 6 additions & 4 deletions src/extension/notebook/malloy_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {errorMessage} from '../../common/errors';
import {BuildModelRequest, CellMetadata, QueryCost} from '../../common/types';
import {convertFromBytes} from '../../common/convert_to_bytes';
import {BaseLanguageClient} from 'vscode-languageclient';
import {SerializedExplore} from '@malloydata/malloy';
import {FetchModelMessage} from '../../common/message_types';

const NO_QUERY = 'Model has no queries.';

Expand Down Expand Up @@ -244,12 +244,14 @@ class MalloyController {
vscode.NotebookCellOutputItem.text('Loading Schema Information'),
]),
]);
const serializedExplores: SerializedExplore[] =
await this.client.sendRequest('malloy/fetchModel', request);
const model: FetchModelMessage = await this.client.sendRequest(
'malloy/fetchModel',
request
);
execution.replaceOutput([
new vscode.NotebookCellOutput([
vscode.NotebookCellOutputItem.json(
serializedExplores,
model,
'x-application/malloy-schema'
),
]),
Expand Down
27 changes: 21 additions & 6 deletions src/extension/notebook/renderer/schema_entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ import React from 'react';
import {StyleSheetManager} from 'styled-components';
import {ActivationFunction} from 'vscode-notebook-renderer';
import {SchemaRenderer} from '../../webviews/components/SchemaRenderer';
import {Explore, Field, SerializedExplore} from '@malloydata/malloy';
import {Explore, Field, NamedQuery} from '@malloydata/malloy';
import {fieldType} from '../../common/schema';
import {FetchModelMessage} from '../../../common/message_types';

export const activate: ActivationFunction = ({postMessage}) => {
return {
Expand Down Expand Up @@ -58,7 +59,7 @@ export const activate: ActivationFunction = ({postMessage}) => {
};

interface SchemaRendererWrapperProps {
results: SerializedExplore[];
results: FetchModelMessage;
postMessage?: (message: unknown) => void;
}

Expand All @@ -73,15 +74,16 @@ const SchemaRendererWrapper = ({
postMessage,
}: SchemaRendererWrapperProps) => {
const [explores, setExplores] = React.useState<Explore[]>();
const [queries, setQueries] = React.useState<NamedQuery[]>();

React.useEffect(() => {
if (results) {
const explores = results.map(json => Explore.fromJSON(json));
setExplores(explores);
setExplores(results.explores.map(json => Explore.fromJSON(json)));
setQueries(results.queries);
}
}, [results]);

if (!explores) {
if (!explores || !queries) {
return null;
}

Expand Down Expand Up @@ -114,5 +116,18 @@ const SchemaRendererWrapper = ({
}
};

return <SchemaRenderer explores={explores} onFieldClick={onFieldClick} />;
const onQueryClick = (query: NamedQuery) => {
const type = 'malloy.runNamedQuery';
const args = [query.name];
postMessage?.({type, args});
};

return (
<SchemaRenderer
explores={explores}
queries={queries}
onFieldClick={onFieldClick}
onQueryClick={onQueryClick}
/>
);
};
17 changes: 5 additions & 12 deletions src/extension/tree_views/schema_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,7 @@
import * as vscode from 'vscode';
import {Utils} from 'vscode-uri';

import {
Explore,
Field,
QueryField,
AtomicField,
SerializedExplore,
} from '@malloydata/malloy';
import {Explore, Field, QueryField, AtomicField} from '@malloydata/malloy';
import numberIcon from '../../media/number.svg';
import numberAggregateIcon from '../../media/number-aggregate.svg';
import booleanIcon from '../../media/boolean.svg';
Expand All @@ -45,6 +39,7 @@ import {MALLOY_EXTENSION_STATE} from '../state';
import {BaseLanguageClient} from 'vscode-languageclient/node';
import {BuildModelRequest} from '../../common/types';
import {exploreSubtype, fieldType, isFieldAggregate} from '../common/schema';
import {FetchModelMessage} from '../../common/message_types';

export class SchemaProvider
implements vscode.TreeDataProvider<ExploreItem | FieldItem>
Expand Down Expand Up @@ -146,14 +141,12 @@ async function getStructs(
version: document.version,
languageId: document.languageId,
};
const serialized_explores: SerializedExplore[] = await client.sendRequest(
const model: FetchModelMessage = await client.sendRequest(
'malloy/fetchModel',
request
);
const explores = serialized_explores.map(explore =>
Explore.fromJSON(explore)
);
return Object.values(explores).sort(exploresByName);
const explores = model.explores.map(explore => Explore.fromJSON(explore));
return explores.sort(exploresByName);
} catch (error) {
return undefined;
}
Expand Down
29 changes: 27 additions & 2 deletions src/extension/webviews/components/SchemaRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

import * as React from 'react';
import styled from 'styled-components';
import {Explore, Field} from '@malloydata/malloy';
import {Explore, Field, NamedQuery} from '@malloydata/malloy';
import {exploreSubtype, fieldType, isFieldAggregate} from '../../common/schema';
import NumberIcon from '../../../media/number.svg';
import NumberAggregateIcon from '../../../media/number-aggregate.svg';
Expand All @@ -40,8 +40,10 @@ import OneToOneIcon from '../../../media/one_to_one.svg';
*/
export interface SchemaRendererProps {
explores: Explore[];
queries: NamedQuery[];
defaultShow?: boolean;
onFieldClick?: (field: Field) => void;
onQueryClick?: (query: NamedQuery) => void;
}

/**
Expand Down Expand Up @@ -148,7 +150,7 @@ Path: ${path}${path ? '.' : ''}${fieldName}
Type: ${type}`;
}

const sortByName = (a: Field | Explore, b: Field | Explore) =>
const sortByName = (a: {name: string}, b: {name: string}) =>
a.name.localeCompare(b.name);

/**
Expand Down Expand Up @@ -193,8 +195,10 @@ function bucketFields(fields: Field[]) {
*/
export const SchemaRenderer: React.FC<SchemaRendererProps> = ({
explores,
queries,
defaultShow = false,
onFieldClick,
onQueryClick,
}) => {
if (!explores || !explores.length) {
return <b>No Schema Information</b>;
Expand Down Expand Up @@ -300,9 +304,30 @@ export const SchemaRenderer: React.FC<SchemaRendererProps> = ({
);
};

const QueryItem = ({query}: {query: NamedQuery}) => {
const onClick = () => {
onQueryClick?.(query);
};
const clickable = onQueryClick ? 'clickable' : '';

return (
<div className={`field ${clickable}`} onClick={onClick}>
{getIconElement('query', false)}
<span className="field_name">{query.name}</span>
</div>
);
};

return (
<SchemaTree>
<ul>
<li>
<div className="field_list">
{queries.sort(sortByName).map(query => (
<QueryItem key={query.name} query={query} />
))}
</div>
</li>
{explores.sort(sortByName).map(explore => (
<StructItem key={explore.name} explore={explore} path={''} />
))}
Expand Down
1 change: 1 addition & 0 deletions src/extension/webviews/query_page/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ export const App: React.FC = () => {
<Scroll>
<SchemaRenderer
explores={results.schema}
queries={[]}
defaultShow={true}
onFieldClick={onFieldClick}
/>
Expand Down
24 changes: 21 additions & 3 deletions src/server/translate_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ import {
MalloyError,
Model,
ModelMaterializer,
NamedModelObject,
NamedQuery,
Runtime,
SerializedExplore,
} from '@malloydata/malloy';
import {TextDocument} from 'vscode-languageserver-textdocument';

Expand All @@ -39,6 +40,10 @@ import {
MalloySQLSQLStatement,
MalloySQLStatementType,
} from '@malloydata/malloy-sql';
import {FetchModelMessage} from '../common/message_types';

const isNamedQuery = (object: NamedModelObject): object is NamedQuery =>
object.type === 'query';

export class TranslateCache implements TranslateCache {
cache = new Map<string, {model: Model; version: number}>();
Expand All @@ -50,13 +55,26 @@ export class TranslateCache implements TranslateCache {
) {
connection.onRequest(
'malloy/fetchModel',
async (event: BuildModelRequest): Promise<SerializedExplore[]> => {
async (event: BuildModelRequest): Promise<FetchModelMessage> => {
const model = await this.translateWithCache(
event.uri,
event.version,
event.languageId
);
return model?.explores.map(explore => explore.toJSON()) || [];
if (model) {
return {
explores: model.explores.map(explore => explore.toJSON()) || [],
// TODO(whscullin) - Create non-backdoor access method
queries: Object.values(model._modelDef.contents).filter(
isNamedQuery
),
};
} else {
return {
explores: [],
queries: [],
};
}
}
);
}
Expand Down

0 comments on commit 23e82d9

Please sign in to comment.