sqlui 0.1.17 → 0.1.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/app/database_config.rb +30 -0
- data/app/server.rb +228 -57
- data/app/sql_parser.rb +17 -0
- data/app/sqlui_config.rb +49 -0
- data/app/views/databases.erb +14 -13
- data/client/resources/sqlui.js +262 -257
- metadata +8 -6
- data/app/sqlui.rb +0 -230
data/client/resources/sqlui.js
CHANGED
@@ -23848,177 +23848,179 @@ var sqlui = (function (exports) {
|
|
23848
23848
|
*/
|
23849
23849
|
const StandardSQL = /*@__PURE__*/SQLDialect.define({});
|
23850
23850
|
|
23851
|
-
|
23851
|
+
/* global google */
|
23852
|
+
|
23853
|
+
function init (parent, onSubmit) {
|
23852
23854
|
const fixedHeightEditor = EditorView.theme({
|
23853
|
-
|
23855
|
+
'.cm-scroller': { height: '200px', overflow: 'auto', resize: 'vertical' }
|
23854
23856
|
});
|
23855
23857
|
window.editorView = new EditorView({
|
23856
23858
|
state: EditorState.create({
|
23857
23859
|
extensions: [
|
23858
23860
|
keymap.of([
|
23859
|
-
{key:
|
23861
|
+
{ key: 'Ctrl-Enter', run: onSubmit, preventDefault: true },
|
23860
23862
|
...defaultKeymap
|
23861
23863
|
]),
|
23862
23864
|
basicSetup,
|
23863
23865
|
sql(),
|
23864
23866
|
fixedHeightEditor,
|
23865
|
-
placeholder(
|
23867
|
+
placeholder('Ctrl-Enter to submit')
|
23866
23868
|
]
|
23867
23869
|
}),
|
23868
|
-
parent
|
23870
|
+
parent
|
23869
23871
|
});
|
23870
23872
|
}
|
23871
23873
|
|
23872
|
-
function getCursor() {
|
23873
|
-
return window.editorView.state.selection.main.head
|
23874
|
+
function getCursor () {
|
23875
|
+
return window.editorView.state.selection.main.head
|
23874
23876
|
}
|
23875
23877
|
|
23876
|
-
function setCursor(cursor) {
|
23877
|
-
window.editorView.dispatch({selection: {anchor: Math.min(cursor, window.editorView.state.doc.length)}});
|
23878
|
+
function setCursor (cursor) {
|
23879
|
+
window.editorView.dispatch({ selection: { anchor: Math.min(cursor, window.editorView.state.doc.length) } });
|
23878
23880
|
}
|
23879
23881
|
|
23880
|
-
function focus() {
|
23882
|
+
function focus () {
|
23881
23883
|
window.editorView.focus();
|
23882
23884
|
}
|
23883
23885
|
|
23884
|
-
function getValue() {
|
23885
|
-
return window.editorView.state.doc.toString()
|
23886
|
+
function getValue () {
|
23887
|
+
return window.editorView.state.doc.toString()
|
23886
23888
|
}
|
23887
23889
|
|
23888
|
-
function setValue(value) {
|
23890
|
+
function setValue (value) {
|
23889
23891
|
window.editorView.dispatch({
|
23890
23892
|
changes: {
|
23891
23893
|
from: 0,
|
23892
23894
|
to: window.editorView.state.doc.length,
|
23893
23895
|
insert: value
|
23894
|
-
}
|
23896
|
+
}
|
23895
23897
|
});
|
23896
23898
|
}
|
23897
23899
|
|
23898
|
-
function selectTab(tab) {
|
23900
|
+
function selectTab (tab) {
|
23899
23901
|
window.tab = tab;
|
23900
23902
|
const url = new URL(window.location);
|
23901
|
-
if (url.searchParams.has(
|
23902
|
-
if (url.searchParams.get(
|
23903
|
-
if (tab ===
|
23904
|
-
url.searchParams.delete(
|
23905
|
-
window.history.pushState({},
|
23906
|
-
return route()
|
23903
|
+
if (url.searchParams.has('tab')) {
|
23904
|
+
if (url.searchParams.get('tab') !== tab) {
|
23905
|
+
if (tab === 'query') {
|
23906
|
+
url.searchParams.delete('tab');
|
23907
|
+
window.history.pushState({}, '', url);
|
23908
|
+
return route()
|
23907
23909
|
} else {
|
23908
|
-
url.searchParams.set(
|
23909
|
-
window.history.pushState({},
|
23910
|
-
return route()
|
23910
|
+
url.searchParams.set('tab', tab);
|
23911
|
+
window.history.pushState({}, '', url);
|
23912
|
+
return route()
|
23911
23913
|
}
|
23912
23914
|
}
|
23913
23915
|
} else {
|
23914
|
-
if (tab !==
|
23915
|
-
url.searchParams.set(
|
23916
|
-
window.history.pushState({},
|
23917
|
-
return route()
|
23916
|
+
if (tab !== 'query') {
|
23917
|
+
url.searchParams.set('tab', tab);
|
23918
|
+
window.history.pushState({}, '', url);
|
23919
|
+
return route()
|
23918
23920
|
}
|
23919
23921
|
}
|
23920
23922
|
|
23921
23923
|
const tabElement = document.getElementById(`${tab}-tab-button`);
|
23922
|
-
Array.prototype.forEach.call(document.getElementsByClassName(
|
23923
|
-
selected.classList.remove(
|
23924
|
-
selected.classList.add(
|
23924
|
+
Array.prototype.forEach.call(document.getElementsByClassName('selected-tab-button'), function (selected) {
|
23925
|
+
selected.classList.remove('selected-tab-button');
|
23926
|
+
selected.classList.add('tab-button');
|
23925
23927
|
});
|
23926
|
-
tabElement.classList.remove(
|
23927
|
-
tabElement.classList.add(
|
23928
|
+
tabElement.classList.remove('tab-button');
|
23929
|
+
tabElement.classList.add('selected-tab-button');
|
23928
23930
|
|
23929
|
-
Array.prototype.forEach.call(document.getElementsByClassName(
|
23930
|
-
selected.style.display =
|
23931
|
+
Array.prototype.forEach.call(document.getElementsByClassName('tab-content-element'), function (selected) {
|
23932
|
+
selected.style.display = 'none';
|
23931
23933
|
});
|
23932
23934
|
|
23933
23935
|
switch (tab) {
|
23934
|
-
case
|
23936
|
+
case 'query':
|
23935
23937
|
selectQueryTab();
|
23936
|
-
break
|
23937
|
-
case
|
23938
|
+
break
|
23939
|
+
case 'graph':
|
23938
23940
|
selectGraphTab();
|
23939
|
-
break
|
23940
|
-
case
|
23941
|
+
break
|
23942
|
+
case 'saved':
|
23941
23943
|
selectSavedTab();
|
23942
|
-
break
|
23943
|
-
case
|
23944
|
+
break
|
23945
|
+
case 'structure':
|
23944
23946
|
selectStructureTab();
|
23945
|
-
break
|
23947
|
+
break
|
23946
23948
|
default:
|
23947
|
-
throw `Unexpected tab: ${tab}
|
23949
|
+
throw new Error(`Unexpected tab: ${tab}`)
|
23948
23950
|
}
|
23949
23951
|
}
|
23950
23952
|
|
23951
|
-
function selectStructureTab() {
|
23952
|
-
Array.prototype.forEach.call(document.getElementsByClassName(
|
23953
|
-
selected.style.display =
|
23953
|
+
function selectStructureTab () {
|
23954
|
+
Array.prototype.forEach.call(document.getElementsByClassName('structure-element'), function (selected) {
|
23955
|
+
selected.style.display = 'flex';
|
23954
23956
|
});
|
23955
23957
|
|
23956
23958
|
if (window.structureLoaded) {
|
23957
|
-
return
|
23959
|
+
return
|
23958
23960
|
}
|
23959
23961
|
|
23960
|
-
const schemasElement = document.getElementById(
|
23961
|
-
const tablesElement = document.getElementById(
|
23962
|
-
const columnsElement = document.getElementById(
|
23963
|
-
const indexesElement = document.getElementById(
|
23962
|
+
const schemasElement = document.getElementById('schemas');
|
23963
|
+
const tablesElement = document.getElementById('tables');
|
23964
|
+
const columnsElement = document.getElementById('columns');
|
23965
|
+
const indexesElement = document.getElementById('indexes');
|
23964
23966
|
|
23965
|
-
const schemaNames = Object.keys(window.metadata
|
23966
|
-
if (schemaNames.length
|
23967
|
+
const schemaNames = Object.keys(window.metadata.schemas);
|
23968
|
+
if (schemaNames.length === 1) {
|
23967
23969
|
schemasElement.style.display = 'none';
|
23968
23970
|
// TODO: duplicate code
|
23969
|
-
while(tablesElement.firstChild) {
|
23971
|
+
while (tablesElement.firstChild) {
|
23970
23972
|
tablesElement.removeChild(tablesElement.firstChild);
|
23971
23973
|
}
|
23972
23974
|
const schemaName = schemaNames[0];
|
23973
|
-
const schema = window.metadata
|
23974
|
-
const tableNames = Object.keys(schema
|
23975
|
-
tableNames.forEach(function(tableName) {
|
23976
|
-
const optionElement = document.createElement(
|
23975
|
+
const schema = window.metadata.schemas[schemaName];
|
23976
|
+
const tableNames = Object.keys(schema.tables);
|
23977
|
+
tableNames.forEach(function (tableName) {
|
23978
|
+
const optionElement = document.createElement('option');
|
23977
23979
|
optionElement.value = tableName;
|
23978
23980
|
optionElement.innerText = tableName;
|
23979
23981
|
tablesElement.appendChild(optionElement);
|
23980
23982
|
});
|
23981
23983
|
} else {
|
23982
23984
|
schemasElement.style.display = 'flex';
|
23983
|
-
schemaNames.forEach(function(schemaName) {
|
23984
|
-
const optionElement = document.createElement(
|
23985
|
+
schemaNames.forEach(function (schemaName) {
|
23986
|
+
const optionElement = document.createElement('option');
|
23985
23987
|
optionElement.value = schemaName;
|
23986
23988
|
optionElement.innerText = schemaName;
|
23987
23989
|
schemasElement.appendChild(optionElement);
|
23988
23990
|
});
|
23989
|
-
schemasElement.addEventListener(
|
23990
|
-
while(tablesElement.firstChild) {
|
23991
|
+
schemasElement.addEventListener('change', function () {
|
23992
|
+
while (tablesElement.firstChild) {
|
23991
23993
|
tablesElement.removeChild(tablesElement.firstChild);
|
23992
23994
|
}
|
23993
23995
|
const schemaName = schemasElement.value;
|
23994
|
-
const schema = window.metadata
|
23995
|
-
const tableNames = Object.keys(schema
|
23996
|
-
tableNames.forEach(function(tableName) {
|
23997
|
-
const optionElement = document.createElement(
|
23996
|
+
const schema = window.metadata.schemas[schemaName];
|
23997
|
+
const tableNames = Object.keys(schema.tables);
|
23998
|
+
tableNames.forEach(function (tableName) {
|
23999
|
+
const optionElement = document.createElement('option');
|
23998
24000
|
optionElement.value = tableName;
|
23999
24001
|
optionElement.innerText = tableName;
|
24000
24002
|
tablesElement.appendChild(optionElement);
|
24001
24003
|
});
|
24002
24004
|
});
|
24003
24005
|
}
|
24004
|
-
tablesElement.addEventListener(
|
24005
|
-
while(columnsElement.firstChild) {
|
24006
|
+
tablesElement.addEventListener('change', function () {
|
24007
|
+
while (columnsElement.firstChild) {
|
24006
24008
|
columnsElement.removeChild(columnsElement.firstChild);
|
24007
24009
|
}
|
24008
|
-
while(indexesElement.firstChild) {
|
24010
|
+
while (indexesElement.firstChild) {
|
24009
24011
|
indexesElement.removeChild(indexesElement.firstChild);
|
24010
24012
|
}
|
24011
|
-
const schemaName = schemaNames.length
|
24013
|
+
const schemaName = schemaNames.length === 1 ? schemaNames[0] : schemasElement.value;
|
24012
24014
|
const tableName = tablesElement.value;
|
24013
|
-
const table = window.metadata
|
24015
|
+
const table = window.metadata.schemas[schemaName].tables[tableName];
|
24014
24016
|
|
24015
|
-
const columnEntries = Object.entries(table
|
24017
|
+
const columnEntries = Object.entries(table.columns);
|
24016
24018
|
if (columnEntries.length > 0) {
|
24017
24019
|
const columns = Object.keys(columnEntries[0][1]);
|
24018
24020
|
const rows = [];
|
24019
|
-
for (const [
|
24021
|
+
for (const [, column] of columnEntries) {
|
24020
24022
|
const row = [];
|
24021
|
-
for (const [
|
24023
|
+
for (const [, value] of Object.entries(column)) {
|
24022
24024
|
row.push(value);
|
24023
24025
|
}
|
24024
24026
|
rows.push(row);
|
@@ -24026,7 +24028,7 @@ var sqlui = (function (exports) {
|
|
24026
24028
|
createTable(columnsElement, columns, rows);
|
24027
24029
|
}
|
24028
24030
|
|
24029
|
-
const indexEntries = Object.entries(table
|
24031
|
+
const indexEntries = Object.entries(table.indexes);
|
24030
24032
|
if (indexEntries.length > 0) {
|
24031
24033
|
const firstIndex = indexEntries[0][1];
|
24032
24034
|
const indexColumns = Object.keys(firstIndex);
|
@@ -24034,10 +24036,10 @@ var sqlui = (function (exports) {
|
|
24034
24036
|
const columns = indexColumnKeys;
|
24035
24037
|
|
24036
24038
|
const rows = [];
|
24037
|
-
for (const [
|
24038
|
-
for (const [
|
24039
|
+
for (const [, index] of indexEntries) {
|
24040
|
+
for (const [, column] of Object.entries(index)) {
|
24039
24041
|
const row = [];
|
24040
|
-
for (const [
|
24042
|
+
for (const [, value] of Object.entries(column)) {
|
24041
24043
|
row.push(value);
|
24042
24044
|
}
|
24043
24045
|
rows.push(row);
|
@@ -24049,32 +24051,34 @@ var sqlui = (function (exports) {
|
|
24049
24051
|
window.structureLoaded = true;
|
24050
24052
|
}
|
24051
24053
|
|
24052
|
-
function createTable(parent, columns, rows) {
|
24053
|
-
const tableElement = document.createElement(
|
24054
|
-
const theadElement = document.createElement(
|
24055
|
-
const headerTrElement = document.createElement(
|
24056
|
-
const tbodyElement = document.createElement(
|
24054
|
+
function createTable (parent, columns, rows) {
|
24055
|
+
const tableElement = document.createElement('table');
|
24056
|
+
const theadElement = document.createElement('thead');
|
24057
|
+
const headerTrElement = document.createElement('tr');
|
24058
|
+
const tbodyElement = document.createElement('tbody');
|
24057
24059
|
theadElement.appendChild(headerTrElement);
|
24058
24060
|
tableElement.appendChild(theadElement);
|
24059
24061
|
tableElement.appendChild(tbodyElement);
|
24060
24062
|
parent.appendChild(tableElement);
|
24061
24063
|
|
24062
|
-
columns.forEach(function(columnName) {
|
24063
|
-
const headerElement = document.createElement(
|
24064
|
+
columns.forEach(function (columnName) {
|
24065
|
+
const headerElement = document.createElement('th');
|
24066
|
+
headerElement.classList.add('cell');
|
24064
24067
|
headerElement.innerText = columnName;
|
24065
24068
|
headerTrElement.appendChild(headerElement);
|
24066
24069
|
});
|
24067
24070
|
headerTrElement.appendChild(document.createElement('th'));
|
24068
24071
|
let highlight = false;
|
24069
|
-
rows.forEach(function(row) {
|
24070
|
-
const rowElement = document.createElement(
|
24072
|
+
rows.forEach(function (row) {
|
24073
|
+
const rowElement = document.createElement('tr');
|
24071
24074
|
if (highlight) {
|
24072
|
-
rowElement.classList.add(
|
24075
|
+
rowElement.classList.add('highlighted-row');
|
24073
24076
|
}
|
24074
24077
|
highlight = !highlight;
|
24075
24078
|
tbodyElement.appendChild(rowElement);
|
24076
|
-
row.forEach(function(value) {
|
24077
|
-
const cellElement = document.createElement(
|
24079
|
+
row.forEach(function (value) {
|
24080
|
+
const cellElement = document.createElement('td');
|
24081
|
+
cellElement.classList.add('cell');
|
24078
24082
|
cellElement.innerText = value;
|
24079
24083
|
rowElement.appendChild(cellElement);
|
24080
24084
|
});
|
@@ -24082,13 +24086,13 @@ var sqlui = (function (exports) {
|
|
24082
24086
|
});
|
24083
24087
|
}
|
24084
24088
|
|
24085
|
-
function selectGraphTab() {
|
24086
|
-
Array.prototype.forEach.call(document.getElementsByClassName(
|
24087
|
-
selected.style.display =
|
24089
|
+
function selectGraphTab () {
|
24090
|
+
Array.prototype.forEach.call(document.getElementsByClassName('graph-element'), function (selected) {
|
24091
|
+
selected.style.display = 'flex';
|
24088
24092
|
});
|
24089
24093
|
|
24090
|
-
google.charts.load('current', {packages: ['corechart', 'line']});
|
24091
|
-
google.charts.setOnLoadCallback(function() {
|
24094
|
+
google.charts.load('current', { packages: ['corechart', 'line'] });
|
24095
|
+
google.charts.setOnLoadCallback(function () {
|
24092
24096
|
loadQueryOrGraphTab(loadGraphResult);
|
24093
24097
|
});
|
24094
24098
|
|
@@ -24097,9 +24101,9 @@ var sqlui = (function (exports) {
|
|
24097
24101
|
setCursor(cursor);
|
24098
24102
|
}
|
24099
24103
|
|
24100
|
-
function selectQueryTab() {
|
24101
|
-
Array.prototype.forEach.call(document.getElementsByClassName(
|
24102
|
-
selected.style.display =
|
24104
|
+
function selectQueryTab () {
|
24105
|
+
Array.prototype.forEach.call(document.getElementsByClassName('query-element'), function (selected) {
|
24106
|
+
selected.style.display = 'flex';
|
24103
24107
|
});
|
24104
24108
|
|
24105
24109
|
const cursor = getCursor();
|
@@ -24109,43 +24113,43 @@ var sqlui = (function (exports) {
|
|
24109
24113
|
loadQueryOrGraphTab(loadQueryResult);
|
24110
24114
|
}
|
24111
24115
|
|
24112
|
-
function selectSavedTab() {
|
24113
|
-
Array.prototype.forEach.call(document.getElementsByClassName(
|
24114
|
-
selected.style.display =
|
24116
|
+
function selectSavedTab () {
|
24117
|
+
Array.prototype.forEach.call(document.getElementsByClassName('saved-element'), function (selected) {
|
24118
|
+
selected.style.display = 'flex';
|
24115
24119
|
});
|
24116
24120
|
|
24117
24121
|
if (window.savedLoaded) {
|
24118
|
-
return
|
24122
|
+
return
|
24119
24123
|
}
|
24120
24124
|
|
24121
|
-
const savedElement = document.getElementById(
|
24125
|
+
const savedElement = document.getElementById('saved-box');
|
24122
24126
|
if (savedElement.children.length > 0) {
|
24123
|
-
return
|
24127
|
+
return
|
24124
24128
|
}
|
24125
24129
|
|
24126
|
-
const saved = window.metadata
|
24130
|
+
const saved = window.metadata.saved;
|
24127
24131
|
if (saved && saved.length === 1) {
|
24128
|
-
setSavedStatus(
|
24132
|
+
setSavedStatus('1 file');
|
24129
24133
|
} else {
|
24130
24134
|
setSavedStatus(`${saved.length} files`);
|
24131
24135
|
}
|
24132
24136
|
saved.forEach(file => {
|
24133
|
-
const divElement = document.createElement(
|
24134
|
-
divElement.addEventListener(
|
24137
|
+
const divElement = document.createElement('div');
|
24138
|
+
divElement.addEventListener('click', function (event) {
|
24135
24139
|
clearResult();
|
24136
24140
|
const url = new URL(window.location);
|
24137
|
-
url.searchParams.delete(
|
24138
|
-
url.searchParams.delete(
|
24139
|
-
url.searchParams.set(
|
24140
|
-
window.history.pushState({},
|
24141
|
+
url.searchParams.delete('sql');
|
24142
|
+
url.searchParams.delete('tab');
|
24143
|
+
url.searchParams.set('file', file.filename);
|
24144
|
+
window.history.pushState({}, '', url);
|
24141
24145
|
route();
|
24142
24146
|
});
|
24143
|
-
const nameElement = document.createElement(
|
24144
|
-
nameElement.innerText = file
|
24147
|
+
const nameElement = document.createElement('h1');
|
24148
|
+
nameElement.innerText = file.filename;
|
24145
24149
|
divElement.appendChild(nameElement);
|
24146
24150
|
|
24147
|
-
const descriptionElement = document.createElement(
|
24148
|
-
descriptionElement.innerText = file
|
24151
|
+
const descriptionElement = document.createElement('p');
|
24152
|
+
descriptionElement.innerText = file.description;
|
24149
24153
|
divElement.appendChild(descriptionElement);
|
24150
24154
|
|
24151
24155
|
savedElement.appendChild(divElement);
|
@@ -24153,38 +24157,38 @@ var sqlui = (function (exports) {
|
|
24153
24157
|
window.savedLoaded = true;
|
24154
24158
|
}
|
24155
24159
|
|
24156
|
-
function submit() {
|
24160
|
+
function submit () {
|
24157
24161
|
const url = new URL(window.location);
|
24158
|
-
url.searchParams.set(
|
24162
|
+
url.searchParams.set('cursor', getCursor());
|
24159
24163
|
|
24160
24164
|
let sql = getValue().trim();
|
24161
|
-
sql = sql ===
|
24165
|
+
sql = sql === '' ? null : sql;
|
24162
24166
|
|
24163
|
-
if (url.searchParams.has(
|
24164
|
-
url.searchParams.delete(
|
24165
|
-
url.searchParams.set(
|
24166
|
-
window.history.pushState({},
|
24167
|
+
if (url.searchParams.has('file')) {
|
24168
|
+
url.searchParams.delete('file');
|
24169
|
+
url.searchParams.set('sql', sql);
|
24170
|
+
window.history.pushState({}, '', url);
|
24167
24171
|
} else {
|
24168
|
-
let sqlParam = url.searchParams.get(
|
24169
|
-
sqlParam = sqlParam ===
|
24172
|
+
let sqlParam = url.searchParams.get('sql')?.trim();
|
24173
|
+
sqlParam = sqlParam === '' ? null : sqlParam;
|
24170
24174
|
|
24171
24175
|
if (sqlParam !== sql) {
|
24172
24176
|
if (sql === null) {
|
24173
|
-
url.searchParams.delete(
|
24174
|
-
window.history.pushState({},
|
24177
|
+
url.searchParams.delete('sql');
|
24178
|
+
window.history.pushState({}, '', url);
|
24175
24179
|
} else {
|
24176
|
-
url.searchParams.set(
|
24177
|
-
window.history.pushState({},
|
24180
|
+
url.searchParams.set('sql', sql);
|
24181
|
+
window.history.pushState({}, '', url);
|
24178
24182
|
}
|
24179
24183
|
} else {
|
24180
|
-
window.history.replaceState({},
|
24184
|
+
window.history.replaceState({}, '', url);
|
24181
24185
|
}
|
24182
24186
|
}
|
24183
24187
|
clearResult();
|
24184
24188
|
route();
|
24185
24189
|
}
|
24186
24190
|
|
24187
|
-
function clearResult() {
|
24191
|
+
function clearResult () {
|
24188
24192
|
clearGraphStatus();
|
24189
24193
|
clearQueryStatus();
|
24190
24194
|
clearGraphBox();
|
@@ -24192,266 +24196,267 @@ var sqlui = (function (exports) {
|
|
24192
24196
|
window.result = null;
|
24193
24197
|
}
|
24194
24198
|
|
24195
|
-
function clearQueryStatus() {
|
24196
|
-
document.getElementById(
|
24199
|
+
function clearQueryStatus () {
|
24200
|
+
document.getElementById('query-status').innerText = '';
|
24197
24201
|
}
|
24198
24202
|
|
24199
|
-
function clearGraphStatus() {
|
24200
|
-
document.getElementById(
|
24203
|
+
function clearGraphStatus () {
|
24204
|
+
document.getElementById('graph-status').innerText = '';
|
24201
24205
|
}
|
24202
24206
|
|
24203
|
-
function clearResultBox() {
|
24204
|
-
const resultElement = document.getElementById(
|
24205
|
-
while(resultElement.firstChild) {
|
24207
|
+
function clearResultBox () {
|
24208
|
+
const resultElement = document.getElementById('result-box');
|
24209
|
+
while (resultElement.firstChild) {
|
24206
24210
|
resultElement.removeChild(resultElement.firstChild);
|
24207
24211
|
}
|
24208
24212
|
}
|
24209
24213
|
|
24210
|
-
function clearGraphBox() {
|
24211
|
-
const graphElement = document.getElementById(
|
24212
|
-
while(graphElement.firstChild) {
|
24214
|
+
function clearGraphBox () {
|
24215
|
+
const graphElement = document.getElementById('graph-box');
|
24216
|
+
while (graphElement.firstChild) {
|
24213
24217
|
graphElement.removeChild(graphElement.firstChild);
|
24214
24218
|
}
|
24215
24219
|
}
|
24216
24220
|
|
24217
|
-
function fetchSql(sql, cursor, callback) {
|
24218
|
-
fetch(
|
24219
|
-
|
24220
|
-
|
24221
|
-
|
24221
|
+
function fetchSql (sql, cursor, callback) {
|
24222
|
+
fetch('query', {
|
24223
|
+
headers: {
|
24224
|
+
Accept: 'application/json',
|
24225
|
+
'Content-Type': 'application/json'
|
24222
24226
|
},
|
24223
|
-
|
24224
|
-
|
24225
|
-
|
24226
|
-
|
24227
|
+
method: 'POST',
|
24228
|
+
body: JSON.stringify({
|
24229
|
+
sql,
|
24230
|
+
cursor
|
24227
24231
|
})
|
24228
24232
|
})
|
24229
|
-
|
24230
|
-
|
24233
|
+
.then((response) => response.json())
|
24234
|
+
.then((result) => callback(result));
|
24231
24235
|
}
|
24232
24236
|
|
24233
|
-
function fetchFile(name, callback) {
|
24237
|
+
function fetchFile (name, callback) {
|
24234
24238
|
fetch(`query_file?file=${name}`, {
|
24235
|
-
|
24236
|
-
|
24239
|
+
headers: {
|
24240
|
+
Accept: 'application/json'
|
24237
24241
|
},
|
24238
|
-
|
24242
|
+
method: 'GET'
|
24239
24243
|
})
|
24240
|
-
|
24241
|
-
|
24244
|
+
.then((response) => response.json())
|
24245
|
+
.then((result) => callback(result));
|
24242
24246
|
}
|
24243
24247
|
|
24244
|
-
function fetchMetadata(callback) {
|
24245
|
-
fetch(
|
24246
|
-
|
24247
|
-
|
24248
|
+
function fetchMetadata (callback) {
|
24249
|
+
fetch('metadata', {
|
24250
|
+
headers: {
|
24251
|
+
Accept: 'application/json'
|
24248
24252
|
},
|
24249
|
-
|
24253
|
+
method: 'GET'
|
24250
24254
|
})
|
24251
|
-
|
24252
|
-
|
24255
|
+
.then((response) => response.json())
|
24256
|
+
.then((result) => callback(result));
|
24253
24257
|
}
|
24254
24258
|
|
24255
|
-
function loadQueryOrGraphTab(callback) {
|
24259
|
+
function loadQueryOrGraphTab (callback) {
|
24256
24260
|
const params = new URLSearchParams(window.location.search);
|
24257
|
-
const sql = params.get(
|
24258
|
-
const file = params.get(
|
24259
|
-
const cursor = params.has(
|
24261
|
+
const sql = params.get('sql');
|
24262
|
+
const file = params.get('file');
|
24263
|
+
const cursor = params.has('cursor') ? params.get('cursor') : 0;
|
24260
24264
|
|
24261
|
-
if (params.has(
|
24265
|
+
if (params.has('sql') && window.result && sql === window.result.query) {
|
24262
24266
|
callback();
|
24263
|
-
return
|
24264
|
-
} else if (params.has(
|
24267
|
+
return
|
24268
|
+
} else if (params.has('file') && window.result && file === window.result.file) {
|
24265
24269
|
callback();
|
24266
|
-
return
|
24270
|
+
return
|
24267
24271
|
}
|
24268
24272
|
|
24269
|
-
if (params.has(
|
24273
|
+
if (params.has('file') && params.has('sql') && cursor === window.result.cursor) {
|
24270
24274
|
// TODO: show an error.
|
24271
|
-
throw
|
24275
|
+
throw new Error('You can only specify a file or sql, not both.')
|
24272
24276
|
}
|
24273
24277
|
|
24274
|
-
|
24278
|
+
clearResult();
|
24279
|
+
|
24280
|
+
if (params.has('sql')) {
|
24275
24281
|
setValue(sql);
|
24276
|
-
const cursor = params.has(
|
24277
|
-
fetchSql(params.get(
|
24282
|
+
const cursor = params.has('cursor') ? params.get('cursor') : 0;
|
24283
|
+
fetchSql(params.get('sql'), cursor, function (result) {
|
24278
24284
|
window.result = result;
|
24279
24285
|
callback();
|
24280
24286
|
});
|
24281
|
-
} else if (params.has(
|
24282
|
-
setValue(
|
24283
|
-
fetchFile(file, function(result) {
|
24287
|
+
} else if (params.has('file')) {
|
24288
|
+
setValue('');
|
24289
|
+
fetchFile(file, function (result) {
|
24284
24290
|
window.result = result;
|
24285
|
-
if (window.result
|
24286
|
-
setValue(result
|
24291
|
+
if (window.result.query) {
|
24292
|
+
setValue(result.query);
|
24287
24293
|
}
|
24288
24294
|
callback();
|
24289
24295
|
});
|
24290
24296
|
}
|
24291
|
-
if (params.has(
|
24297
|
+
if (params.has('cursor')) {
|
24292
24298
|
focus();
|
24293
24299
|
setCursor(cursor);
|
24294
24300
|
}
|
24295
24301
|
}
|
24296
24302
|
|
24297
|
-
function loadQueryResult() {
|
24298
|
-
const resultElement = document.getElementById(
|
24303
|
+
function loadQueryResult () {
|
24304
|
+
const resultElement = document.getElementById('result-box');
|
24299
24305
|
if (resultElement.children.length > 0) {
|
24300
|
-
return
|
24306
|
+
return
|
24301
24307
|
}
|
24302
24308
|
|
24303
24309
|
setQueryStatus(window.result);
|
24304
24310
|
|
24305
|
-
if (!window.result
|
24306
|
-
return
|
24311
|
+
if (!window.result.rows) {
|
24312
|
+
return
|
24307
24313
|
}
|
24308
24314
|
|
24309
|
-
const tableElement = document.createElement(
|
24310
|
-
const theadElement = document.createElement(
|
24311
|
-
const headerElement = document.createElement(
|
24312
|
-
const tbodyElement = document.createElement(
|
24315
|
+
const tableElement = document.createElement('table');
|
24316
|
+
const theadElement = document.createElement('thead');
|
24317
|
+
const headerElement = document.createElement('tr');
|
24318
|
+
const tbodyElement = document.createElement('tbody');
|
24313
24319
|
theadElement.appendChild(headerElement);
|
24314
24320
|
tableElement.appendChild(theadElement);
|
24315
24321
|
tableElement.appendChild(tbodyElement);
|
24316
24322
|
resultElement.appendChild(tableElement);
|
24317
|
-
|
24318
|
-
window.result
|
24319
|
-
const template = document.createElement(
|
24320
|
-
template.innerHTML = `<th>${column}</th>`;
|
24323
|
+
|
24324
|
+
window.result.columns.forEach(column => {
|
24325
|
+
const template = document.createElement('template');
|
24326
|
+
template.innerHTML = `<th class="cell">${column}</th>`;
|
24321
24327
|
headerElement.appendChild(template.content.firstChild);
|
24322
24328
|
});
|
24323
24329
|
headerElement.appendChild(document.createElement('th'));
|
24324
24330
|
let highlight = false;
|
24325
|
-
window.result
|
24326
|
-
const rowElement = document.createElement(
|
24331
|
+
window.result.rows.forEach(function (row) {
|
24332
|
+
const rowElement = document.createElement('tr');
|
24327
24333
|
if (highlight) {
|
24328
|
-
rowElement.classList.add(
|
24334
|
+
rowElement.classList.add('highlighted-row');
|
24329
24335
|
}
|
24330
24336
|
highlight = !highlight;
|
24331
24337
|
tbodyElement.appendChild(rowElement);
|
24332
|
-
row.forEach(function(value) {
|
24333
|
-
const template = document.createElement(
|
24334
|
-
template.innerHTML = `<td>${value}</td>`;
|
24338
|
+
row.forEach(function (value) {
|
24339
|
+
const template = document.createElement('template');
|
24340
|
+
template.innerHTML = `<td class="cell">${value}</td>`;
|
24335
24341
|
rowElement.appendChild(template.content.firstChild);
|
24336
24342
|
});
|
24337
24343
|
rowElement.appendChild(document.createElement('td'));
|
24338
24344
|
});
|
24339
24345
|
|
24340
|
-
document.getElementById(
|
24346
|
+
document.getElementById('result-box').style.display = 'flex';
|
24341
24347
|
}
|
24342
24348
|
|
24343
|
-
function loadGraphResult() {
|
24349
|
+
function loadGraphResult () {
|
24344
24350
|
setGraphStatus(window.result);
|
24345
24351
|
|
24346
|
-
if (!window.result
|
24347
|
-
return
|
24352
|
+
if (!window.result.rows) {
|
24353
|
+
return
|
24348
24354
|
}
|
24349
|
-
if (window.result
|
24350
|
-
return
|
24355
|
+
if (window.result.rows.length === 0 || window.result.columns.length < 2) {
|
24356
|
+
return
|
24351
24357
|
}
|
24352
24358
|
const dataTable = new google.visualization.DataTable();
|
24353
|
-
window.result
|
24354
|
-
dataTable.addColumn(window.result
|
24359
|
+
window.result.columns.forEach((column, index) => {
|
24360
|
+
dataTable.addColumn(window.result.column_types[index], column);
|
24355
24361
|
});
|
24356
24362
|
|
24357
|
-
window.result
|
24363
|
+
window.result.rows.forEach((row) => {
|
24358
24364
|
const rowValues = row.map((value, index) => {
|
24359
|
-
if (window.result
|
24360
|
-
return new Date(value)
|
24365
|
+
if (window.result.column_types[index] === 'date') {
|
24366
|
+
return new Date(value)
|
24361
24367
|
} else {
|
24362
|
-
return value
|
24368
|
+
return value
|
24363
24369
|
}
|
24364
24370
|
});
|
24365
24371
|
dataTable.addRow(rowValues);
|
24366
24372
|
});
|
24367
24373
|
|
24368
|
-
const graphBoxElement = document.getElementById(
|
24374
|
+
const graphBoxElement = document.getElementById('graph-box');
|
24369
24375
|
|
24370
24376
|
const chart = new google.visualization.LineChart(graphBoxElement);
|
24371
24377
|
const options = {
|
24372
|
-
|
24373
|
-
|
24378
|
+
hAxis: {
|
24379
|
+
title: window.result.columns[0]
|
24374
24380
|
},
|
24375
|
-
|
24376
|
-
|
24381
|
+
vAxis: {
|
24382
|
+
title: window.result.columns[1]
|
24377
24383
|
}
|
24378
24384
|
};
|
24379
24385
|
chart.draw(dataTable, options);
|
24380
24386
|
}
|
24381
24387
|
|
24382
|
-
function setGraphStatus(result) {
|
24383
|
-
const statusElement = document.getElementById(
|
24384
|
-
if (!result
|
24388
|
+
function setGraphStatus (result) {
|
24389
|
+
const statusElement = document.getElementById('graph-status');
|
24390
|
+
if (!result.rows) {
|
24385
24391
|
// TODO use a popup
|
24386
|
-
console.log(
|
24392
|
+
console.log('error parsing graph result');
|
24387
24393
|
console.log(JSON.stringify(result, null, 2));
|
24388
|
-
statusElement.innerText =
|
24389
|
-
return
|
24394
|
+
statusElement.innerText = 'error, check console';
|
24395
|
+
return
|
24390
24396
|
}
|
24391
24397
|
|
24392
|
-
if (result
|
24393
|
-
statusElement.innerText = `${result
|
24398
|
+
if (result.total_rows === 1) {
|
24399
|
+
statusElement.innerText = `${result.total_rows} row`;
|
24394
24400
|
} else {
|
24395
|
-
statusElement.innerText = `${result
|
24401
|
+
statusElement.innerText = `${result.total_rows} rows`;
|
24396
24402
|
}
|
24397
24403
|
|
24398
|
-
if (result
|
24399
|
-
statusElement.innerText += ` (truncated to ${result
|
24404
|
+
if (result.total_rows > result.rows.length) {
|
24405
|
+
statusElement.innerText += ` (truncated to ${result.rows.length})`;
|
24400
24406
|
}
|
24401
24407
|
}
|
24402
24408
|
|
24403
|
-
function setQueryStatus(result) {
|
24404
|
-
const statusElement = document.getElementById(
|
24405
|
-
if (!result
|
24409
|
+
function setQueryStatus (result) {
|
24410
|
+
const statusElement = document.getElementById('query-status');
|
24411
|
+
if (!result.rows) {
|
24406
24412
|
// TODO use a popup
|
24407
|
-
console.log(
|
24413
|
+
console.log('error parsing query result');
|
24408
24414
|
console.log(JSON.stringify(result, null, 2));
|
24409
|
-
statusElement.innerText =
|
24410
|
-
return
|
24415
|
+
statusElement.innerText = 'error, check console';
|
24416
|
+
return
|
24411
24417
|
}
|
24412
24418
|
|
24413
|
-
if (result
|
24414
|
-
statusElement.innerText = `${result
|
24419
|
+
if (result.total_rows === 1) {
|
24420
|
+
statusElement.innerText = `${result.total_rows} row`;
|
24415
24421
|
} else {
|
24416
|
-
statusElement.innerText = `${result
|
24422
|
+
statusElement.innerText = `${result.total_rows} rows`;
|
24417
24423
|
}
|
24418
24424
|
|
24419
|
-
if (result
|
24420
|
-
statusElement.innerText += ` (truncated to ${result
|
24425
|
+
if (result.total_rows > result.rows.length) {
|
24426
|
+
statusElement.innerText += ` (truncated to ${result.rows.length})`;
|
24421
24427
|
}
|
24422
24428
|
}
|
24423
24429
|
|
24424
|
-
function setSavedStatus(status) {
|
24425
|
-
document.getElementById(
|
24430
|
+
function setSavedStatus (status) {
|
24431
|
+
document.getElementById('saved-status').innerText = status;
|
24426
24432
|
}
|
24427
24433
|
|
24428
|
-
window.addEventListener(
|
24434
|
+
window.addEventListener('popstate', function (event) {
|
24429
24435
|
route();
|
24430
24436
|
});
|
24431
24437
|
|
24432
|
-
window.addEventListener(
|
24433
|
-
if (window.tab ===
|
24438
|
+
window.addEventListener('resize', function (event) {
|
24439
|
+
if (window.tab === 'graph' && window.result) {
|
24434
24440
|
clearGraphBox();
|
24435
24441
|
loadGraphResult();
|
24436
24442
|
}
|
24437
24443
|
});
|
24438
24444
|
|
24439
|
-
function route() {
|
24440
|
-
selectTab(new URLSearchParams(window.location.search).get(
|
24445
|
+
function route () {
|
24446
|
+
selectTab(new URLSearchParams(window.location.search).get('tab') || 'query');
|
24441
24447
|
}
|
24442
24448
|
|
24443
24449
|
window.onload = function () {
|
24444
|
-
fetchMetadata(function(result) {
|
24450
|
+
fetchMetadata(function (result) {
|
24445
24451
|
window.metadata = result;
|
24446
|
-
if (!result
|
24452
|
+
if (!result.server) {
|
24447
24453
|
// TODO show error
|
24448
|
-
throw
|
24454
|
+
throw new Error('unexpected metadata response')
|
24449
24455
|
}
|
24450
|
-
document.getElementById(
|
24451
|
-
|
24452
|
-
const queryElement = document.getElementById("query");
|
24456
|
+
document.getElementById('header').innerText = result.server;
|
24457
|
+
const queryElement = document.getElementById('query');
|
24453
24458
|
|
24454
|
-
init(queryElement, function() {
|
24459
|
+
init(queryElement, function () {
|
24455
24460
|
submit();
|
24456
24461
|
});
|
24457
24462
|
route();
|