Skip to content

Commit a8849af

Browse files
georgewfishermosabua
authored andcommitted
Add Trino Query UI
1 parent c905f19 commit a8849af

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+51632
-0
lines changed

.gitignore

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

README.md

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Trino Query UI
2+
3+
This Trino Query UI is a new UI component that can be integrated into Trino and run directly from the Trino installation at the `/query/` path. For testing, it can also be run separately and can proxy to a Trino running locally or elsewhere.
4+
5+
![Trino Query UI Demo](demos.gif "Trino Query UI Demo")
6+
7+
Implementation details:
8+
* React Typescript project with Vite
9+
* Using Node.js v20+
10+
* Monaco editor + ANTLR parser using Trino language
11+
12+
## Building and Shipping in Trino
13+
14+
The Query UI builds just like the existing UI in Trino.
15+
1. First you build the TypeScript into Javascript and CSS
16+
2. Then copy the distributable path into Trino.
17+
3. Then modify Trino to respond to the query ui path.
18+
19+
### Building for Integration
20+
21+
```
22+
cd precise
23+
npm run build
24+
```
25+
26+
### Copying into Trino
27+
28+
mkdir -p $TRINO_HOME/core/trino-main/src/main/resources/query_ui_webapp/
29+
cp -r dist/* $TRINO_HOME/core/trino-main/src/main/resources/query_ui_webapp/
30+
31+
### Modifying Trino to Respond to /query/
32+
33+
Modify `$TRINO_HOME/core/trino-main/src/main/java/io/trino/server/ui/WebUiStaticResource.java`:
34+
35+
Add `/query/` path. Note any path can be used:
36+
37+
```java
38+
@GET
39+
@Path("/query")
40+
public Response getQuery(@BeanParam ExternalUriInfo externalUriInfo)
41+
{
42+
return Response.seeOther(externalUriInfo.absolutePath("/query/")).build();
43+
}
44+
45+
// asset files are always visible
46+
@ResourceSecurity(PUBLIC)
47+
@GET
48+
@Path("/query/assets/{path: .*}")
49+
public Response getQueryAssetsFile(@PathParam("path") String path)
50+
throws IOException
51+
{
52+
return getQueryFile("assets/" + path);
53+
}
54+
55+
@ResourceSecurity(PUBLIC)
56+
@GET
57+
@Path("/query/{path: .*}")
58+
public Response getQueryFile(@PathParam("path") String path)
59+
throws IOException
60+
{
61+
if (path.isEmpty()) {
62+
path = "index.html";
63+
}
64+
65+
String fullPath = "/query_ui_webapp/" + path;
66+
if (!isCanonical(fullPath)) {
67+
return Response.status(NOT_FOUND).build();
68+
}
69+
70+
URL resource = getClass().getResource(fullPath);
71+
if (resource == null) {
72+
return Response.status(NOT_FOUND).build();
73+
}
74+
75+
return Response.ok(resource.openStream()).build();
76+
}
77+
78+
private static boolean isCanonical(String fullPath)
79+
{
80+
try {
81+
return new URI(fullPath).normalize().getPath().equals(fullPath);
82+
}
83+
catch (URISyntaxException e) {
84+
return false;
85+
}
86+
}
87+
```
88+
89+
## Development
90+
91+
### Setup the Coding Environment
92+
93+
Tested on Ubuntu and Windows.
94+
95+
1. Install node.js <https://nodejs.org/en/download/> at least v20
96+
2. Create an NPM enviroment using Vite: `npm create vite@latest`, pick *React*, then *Typescript*
97+
3. In the precise folder, install monaco `npm install @monaco-editor/react`
98+
4. Install Typescript Runtime for ANTLR4 `npm install antlr4ng` and the cli `npm install --save-dev antlr4ng-cli`
99+
because <https://github.com/tunnelvisionlabs/antlr4ts> seems abandoned?
100+
101+
### Setup Proxying to Local Trino Instance
102+
103+
To run outside of Trino, update the contents of the `vite.config.ts` with the following so that queries can be properly proxied over to Trino's query endpoint running on `http://localhost:8080` or any other proxy path required.
104+
105+
```tsx
106+
import { defineConfig } from 'vite'
107+
import react from '@vitejs/plugin-react'
108+
109+
// https://vitejs.dev/config/
110+
export default defineConfig({
111+
base: '/query/',
112+
plugins: [react()],
113+
server: {
114+
proxy: {
115+
'/v1': {
116+
target: 'http://localhost:8080',
117+
changeOrigin: true,
118+
secure: false,
119+
},
120+
},
121+
},
122+
});
123+
```
124+
125+
### Build and Run
126+
127+
To run, start:
128+
129+
```shell
130+
cd precise
131+
npm install
132+
npm run dev
133+
```
134+
135+
The local URL will be be displayed which you can open in your browser.
136+
137+
### Building the Parser
138+
139+
To build parser: `npm run antlr4ng`, as configured in **package.json**
140+
141+
## Philosophy
142+
143+
This UI's purpose is to provide an environment where once the cluster is stood up, executing queries and exploring data sets can be done right away. The idended use cases are:
144+
* Initial proof-of-concept queries.
145+
* Exploration of data sets.
146+
* Performance analysis.
147+
* Adhoc query execution.
148+
* Quickly enabling a data engineering team to start work before other integrations are in place.
149+
* Early demos.
150+
151+
The approach taken:
152+
1. Direct integration into Trino UI
153+
- No need for additional authentication hop (although it could be added in the future)
154+
- Auth as the user executing the query if using Oauth2
155+
- Trino does the heavy lifting
156+
2. Don't need to think, just write a query
157+
- Autocomplete must be aware of not just Trino language but tables and columns
158+
- Syntax highlighting, validation
159+
- Comprehensive catalog explorer
160+
3. No black box query execution
161+
- Show progress and details of execution: people ask "why is my query slow" but mostly this is because they are only shown a spinner for 10 minutes.
162+
- Link to Trino query UI to drill into query performance
163+
- Show stages and split counts like Trino console client
164+
4. Easy to navigate
165+
166+
### Gaps and Future Direction
167+
168+
* The ability to save queries and use source control requires either back end capabilities in the Trino service or can utilize Trino to write queries as tables.
169+
* No autocomplete for the Trino function list.
170+
* Basic graphing capabilities - looking at a table is not enough even for inspecting data sets.
171+
* No LLM copilot integration yet, this is done badly in many query UIs and if done well could make query crafting very fast, and solve other issues like translation from other query languages.
172+
* Parameters and string replace: this is partly implemented in `SubstitutionEditor` and should support both SQL parameters and string replacement.

demos.gif

44.4 MB
Loading

precise/.eslintrc.cjs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
root: true,
3+
env: { browser: true, es2020: true },
4+
extends: [
5+
'eslint:recommended',
6+
'plugin:@typescript-eslint/recommended',
7+
'plugin:react-hooks/recommended',
8+
],
9+
ignorePatterns: ['dist', '.eslintrc.cjs'],
10+
parser: '@typescript-eslint/parser',
11+
plugins: ['react-refresh'],
12+
rules: {
13+
'react-refresh/only-export-components': [
14+
'warn',
15+
{ allowConstantExport: true },
16+
],
17+
},
18+
}

precise/index.html

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/png" href="/commander_bunbun.png" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Trino Query Editor</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>

0 commit comments

Comments
 (0)