Skip to content

Commit 94b04cb

Browse files
johallaryhwang
authored andcommitted
Display selected values for schema and catalog dropdowns
Moves data previously stored in nested state objects or refs, to useState hooks. Adds concept of selected values to SqlDropdown component props. This allows react to properly/efficiently render state changes.
1 parent 892cbee commit 94b04cb

File tree

2 files changed

+42
-44
lines changed

2 files changed

+42
-44
lines changed

presto-ui/src/components/SQLClient.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ export default function SQLClientView() {
3535
const sessions: SessionValues = React.useRef({});
3636
const views = [{name: 'SQL', label: 'SQL'}, {name: 'Session', label: 'Session Properties'}];
3737

38-
const executeSQL = (sqlInfo) => {
38+
const executeSQL = (sql, catalog, schema) => {
3939
const client = createClient(
40-
sqlInfo.catalog,
41-
sqlInfo.schema,
40+
catalog,
41+
schema,
4242
Object.keys(sessions.current).map(key => `${key}=${sessions.current[key]}`).join(', ')
4343
);
4444
setValues({ ...values, running: true, results: undefined });
45-
client.query(sqlInfo.sql).then((prestoQuery: PrestoQuery) => {
45+
client.query(sql).then((prestoQuery: PrestoQuery) => {
4646
setValues({ ...values, running: false, results: prestoQuery });
4747
})
4848
.catch((e) => {

presto-ui/src/components/SQLInput.jsx

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -92,40 +92,37 @@ class SyntaxError extends antlr4.error.ErrorListener {
9292
}
9393

9494
// Dropdown for Catalog and Schema
95-
function SQLDropDown({ text, values, onSelect }) {
96-
const items = values || [];
97-
const [data, setData] = React.useState({ items: items, current: undefined });
95+
function SQLDropDown({ text, values = [], onSelect, selected }) {
9896

9997
function selectItem(item) {
100-
if (item !== data.current) {
98+
if (item !== selected) {
10199
onSelect(item);
102-
setData({ ...data, current: item });
103100
}
104101
}
105102

106103
return (
107104
<div className="btn-group">
108105
<button type="button" className="btn btn-secondary dropdown-toggle bg-white text-dark"
109106
data-bs-toggle="dropdown" aria-haspopup="true"
110-
aria-expanded="false">{text}</button>
107+
aria-expanded="false">{selected ?? text}</button>
111108
<ul className="dropdown-menu bg-white">
112-
{items.map((item, idx) => (
113-
<li key={idx}><a href="#" className={clsx('dropdown-item text-dark', data.current === item && 'selected')} onClick={() => selectItem(item)}>{item}</a></li>
109+
{values.map((item, idx) => (
110+
<li key={idx}><a href="#" className={clsx('dropdown-item text-dark', selected === item && 'selected')} onClick={() => selectItem(item)}>{item}</a></li>
114111
))}
115112
</ul>
116113
</div>
117114
);
118115
}
119116

120-
function sqlCleaning(sqlInfo, errorHandler) {
117+
function sqlCleaning(sql, errorHandler) {
121118
const lastSemicolon = /(\s*;\s*)$/m;
122119
const limitRE = /limit\s+(\d+|all)$/im;
123120
const fetchFirstRE = /fetch\s+first\s+(\d+)\s+rows\s+only$/im;
124121
const syntaxError = new SyntaxError();
125122

126123
try {
127-
sqlInfo.sql = sqlInfo.sql.replace(lastSemicolon, '').trim();
128-
const parser = new SqlBaseParser(new antlr4.CommonTokenStream(new SqlBaseLexer(new UpperCaseCharStream(sqlInfo.sql))));
124+
let cleanSql = sql.replace(lastSemicolon, '').trim();
125+
const parser = new SqlBaseParser(new antlr4.CommonTokenStream(new SqlBaseLexer(new UpperCaseCharStream(cleanSql))));
129126
const selectDetector = new SelectListener();
130127
parser.addErrorListener(syntaxError);
131128
antlr4.tree.ParseTreeWalker.DEFAULT.walk(selectDetector, parser.statement());
@@ -136,65 +133,66 @@ function sqlCleaning(sqlInfo, errorHandler) {
136133
}
137134
if (selectDetector.isSelect) {
138135
if (typeof (selectDetector.limit) === 'string' || selectDetector.limit > 100) {
139-
sqlInfo.sql = sqlInfo.sql.replace(limitRE, 'limit 100');
136+
cleanSql= cleanSql.replace(limitRE, 'limit 100');
140137
} else if (selectDetector.fetchFirstNRows > 100) {
141-
sqlInfo.sql = sqlInfo.sql.replace(fetchFirstRE, 'fetch first 100 rows only');
138+
cleanSql = cleanSql.replace(fetchFirstRE, 'fetch first 100 rows only');
142139
} else if (selectDetector.limit === -1 && selectDetector.fetchFirstNRows === -1) {
143-
sqlInfo.sql += ' limit 100';
140+
cleanSql += ' limit 100';
144141
}
145142
}
143+
return cleanSql
146144
} catch (err) {
147145
if (errorHandler) {
148146
errorHandler(err);
149147
}
150148
return false;
151149
}
152-
return true;
153150
}
154151

155152
// SQL Input, including sql text, catalog(optional), and schema(optional)
156153
export function SQLInput({ handleSQL, show, enabled, initialSQL, errorHandler }) {
157-
const sqlInfo = React.useRef({ sql: undefined, catalog: undefined, schema: undefined });
158-
const [data, setData] = React.useState({ catalogs: [], schemas: [] });
159-
const [code, setCode] = React.useState(initialSQL);
160-
154+
const [sql, setSql] = React.useState(initialSQL);
155+
const [catalog, setCatalog] = React.useState(undefined);
156+
const [schema, setSchema] = React.useState(undefined);
157+
const [catalogs, setCatalogs] = React.useState([]);
158+
const [schemas, setSchemas] = React.useState([]);
159+
161160
const checkValue = () => {
162-
if (code.length > 0) {
163-
sqlInfo.current.sql = code;
164-
if (sqlCleaning(sqlInfo.current, errorHandler)) {
165-
setCode(sqlInfo.current.sql);
166-
handleSQL(sqlInfo.current);
161+
if (sql.length > 0) {
162+
let cleanSql = sqlCleaning(sql, errorHandler);
163+
if (cleanSql) {
164+
setSql(cleanSql);
165+
handleSQL(cleanSql, catalog, schema);
167166
}
168167
}
169168
};
170169

171-
async function setCatalog(catalog) {
172-
sqlInfo.current.catalog = catalog;
170+
async function catalogSelected(catalog) {
171+
setCatalog(catalog);
173172
// also reset schema
174-
setData({ ...data, schemas: [] });
173+
setSchema(undefined);
174+
setSchemas([]);
175175
// fetch schemas from the catalog
176176
const client = createClient();
177177
try {
178-
const schemas = await client.getSchemas(catalog);
179-
setData({ ...data, schemas });
178+
const fetchedSchemas = await client.getSchemas(catalog);
179+
setSchemas(fetchedSchemas)
180180
} catch (e) {
181181
// use this to report the issue
182182
console.error(e);
183183
}
184184
}
185-
186-
function setSchema(schema) {
187-
sqlInfo.current.schema = schema;
188-
setData({ ...data });
185+
const schemaSelected = (schema) => {
186+
setSchema(schema);
189187
}
190188

191189
React.useEffect(() => {
192190
//fetch catalogs:
193191
async function getCatalogs() {
194192
const client = createClient();
195193
try {
196-
const catalogs = await client.getCatalogs();
197-
setData({ ...data, catalogs });
194+
const fetchedCatalogs = await client.getCatalogs();
195+
setCatalogs(fetchedCatalogs)
198196
} catch (e) {
199197
// use this to report the issue
200198
console.error(e);
@@ -208,9 +206,9 @@ export function SQLInput({ handleSQL, show, enabled, initialSQL, errorHandler })
208206
<div className="row">
209207
<div className="col-12">
210208
<div className='input-group' role='group'>
211-
<SQLDropDown text='Catalog' values={data.catalogs} onSelect={setCatalog} />
209+
<SQLDropDown text='Catalog' values={catalogs} onSelect={catalogSelected} selected={catalog}/>
212210
&nbsp;
213-
<SQLDropDown text='Schema' values={data.schemas} onSelect={setSchema} />
211+
<SQLDropDown text='Schema' values={schemas} onSelect={schemaSelected} selected={schema}/>
214212
&nbsp;
215213
<div className="btn-group">
216214
<button className={clsx('btn', 'btn-success', !enabled && 'disabled')} type="button" onClick={checkValue}>Run</button>
@@ -221,9 +219,9 @@ export function SQLInput({ handleSQL, show, enabled, initialSQL, errorHandler })
221219
<div className="row">
222220
<div className="col-12">
223221
<Editor
224-
value={code}
225-
onValueChange={code => setCode(code)}
226-
highlight={code => highlight(code, languages.sql)}
222+
value={sql}
223+
onValueChange={setSql}
224+
highlight={val => highlight(val, languages.sql)}
227225
padding={10}
228226
style={{
229227
fontFamily: '"Fira code", "Fira Mono", monospace',

0 commit comments

Comments
 (0)