sqlui 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/app/args.rb +33 -0
- data/app/database_config.rb +7 -7
- data/app/database_metadata.rb +116 -0
- data/app/deep.rb +58 -0
- data/app/mysql_types.rb +33 -0
- data/app/server.rb +125 -217
- data/app/sqlui.rb +36 -0
- data/app/sqlui_config.rb +11 -16
- data/app/views/databases.erb +70 -38
- data/bin/sqlui +3 -1
- data/client/resources/sqlui.css +288 -242
- data/client/resources/sqlui.html +8 -5
- data/client/resources/sqlui.js +168 -82
- metadata +7 -2
data/client/resources/sqlui.js
CHANGED
@@ -4150,7 +4150,7 @@ var sqlui = (function (exports) {
|
|
4150
4150
|
return name
|
4151
4151
|
}
|
4152
4152
|
|
4153
|
-
function getSelection(root) {
|
4153
|
+
function getSelection$1(root) {
|
4154
4154
|
let target;
|
4155
4155
|
// Browsers differ on whether shadow roots have a getSelection
|
4156
4156
|
// method. If it exists, use that, otherwise, call it on the
|
@@ -6773,7 +6773,7 @@ var sqlui = (function (exports) {
|
|
6773
6773
|
this.dom.blur();
|
6774
6774
|
this.dom.focus({ preventScroll: true });
|
6775
6775
|
}
|
6776
|
-
let rawSel = getSelection(this.view.root);
|
6776
|
+
let rawSel = getSelection$1(this.view.root);
|
6777
6777
|
if (!rawSel) ;
|
6778
6778
|
else if (main.empty) {
|
6779
6779
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1612076
|
@@ -6822,7 +6822,7 @@ var sqlui = (function (exports) {
|
|
6822
6822
|
if (this.compositionDeco.size)
|
6823
6823
|
return;
|
6824
6824
|
let cursor = this.view.state.selection.main;
|
6825
|
-
let sel = getSelection(this.view.root);
|
6825
|
+
let sel = getSelection$1(this.view.root);
|
6826
6826
|
if (!sel || !cursor.empty || !cursor.assoc || !sel.modify)
|
6827
6827
|
return;
|
6828
6828
|
let line = LineView.find(this, cursor.head);
|
@@ -7763,7 +7763,7 @@ var sqlui = (function (exports) {
|
|
7763
7763
|
return false;
|
7764
7764
|
// On boundary clicks, check whether the coordinates are inside the
|
7765
7765
|
// selection's client rectangles
|
7766
|
-
let sel = getSelection(view.root);
|
7766
|
+
let sel = getSelection$1(view.root);
|
7767
7767
|
if (!sel || sel.rangeCount == 0)
|
7768
7768
|
return true;
|
7769
7769
|
let rects = sel.getRangeAt(0).getClientRects();
|
@@ -9998,7 +9998,7 @@ var sqlui = (function (exports) {
|
|
9998
9998
|
// https://github.com/codemirror/dev/issues/414
|
9999
9999
|
let range = browser.safari && view.root.nodeType == 11 &&
|
10000
10000
|
deepActiveElement(this.dom.ownerDocument) == this.dom &&
|
10001
|
-
safariSelectionRangeHack(this.view) || getSelection(view.root);
|
10001
|
+
safariSelectionRangeHack(this.view) || getSelection$1(view.root);
|
10002
10002
|
if (!range || this.selectionRange.eq(range))
|
10003
10003
|
return false;
|
10004
10004
|
let local = hasSelection(this.dom, range);
|
@@ -23850,7 +23850,7 @@ var sqlui = (function (exports) {
|
|
23850
23850
|
|
23851
23851
|
/* global google */
|
23852
23852
|
|
23853
|
-
function init (parent, onSubmit) {
|
23853
|
+
function init (parent, onSubmit, onShiftSubmit) {
|
23854
23854
|
const fixedHeightEditor = EditorView.theme({
|
23855
23855
|
'.cm-scroller': { height: '200px', overflow: 'auto', resize: 'vertical' }
|
23856
23856
|
});
|
@@ -23858,7 +23858,7 @@ var sqlui = (function (exports) {
|
|
23858
23858
|
state: EditorState.create({
|
23859
23859
|
extensions: [
|
23860
23860
|
keymap.of([
|
23861
|
-
{ key: 'Ctrl-Enter', run: onSubmit, preventDefault: true },
|
23861
|
+
{ key: 'Ctrl-Enter', run: onSubmit, preventDefault: true, shift: onShiftSubmit },
|
23862
23862
|
...defaultKeymap
|
23863
23863
|
]),
|
23864
23864
|
basicSetup,
|
@@ -23871,12 +23871,19 @@ var sqlui = (function (exports) {
|
|
23871
23871
|
});
|
23872
23872
|
}
|
23873
23873
|
|
23874
|
-
function
|
23875
|
-
return window.editorView.state.selection.main.
|
23874
|
+
function getSelection () {
|
23875
|
+
return [window.editorView.state.selection.main.from, window.editorView.state.selection.main.to]
|
23876
23876
|
}
|
23877
23877
|
|
23878
|
-
function
|
23879
|
-
window.editorView.dispatch(
|
23878
|
+
function setSelection (selection) {
|
23879
|
+
window.editorView.dispatch(
|
23880
|
+
{
|
23881
|
+
selection: {
|
23882
|
+
anchor: Math.min(selection[0], window.editorView.state.doc.length),
|
23883
|
+
head: Math.min(selection[1], window.editorView.state.doc.length)
|
23884
|
+
}
|
23885
|
+
}
|
23886
|
+
);
|
23880
23887
|
}
|
23881
23888
|
|
23882
23889
|
function focus () {
|
@@ -24067,7 +24074,9 @@ var sqlui = (function (exports) {
|
|
24067
24074
|
headerElement.innerText = columnName;
|
24068
24075
|
headerTrElement.appendChild(headerElement);
|
24069
24076
|
});
|
24070
|
-
|
24077
|
+
if (columns.length > 0) {
|
24078
|
+
headerTrElement.appendChild(document.createElement('th'));
|
24079
|
+
}
|
24071
24080
|
let highlight = false;
|
24072
24081
|
rows.forEach(function (row) {
|
24073
24082
|
const rowElement = document.createElement('tr');
|
@@ -24093,12 +24102,12 @@ var sqlui = (function (exports) {
|
|
24093
24102
|
|
24094
24103
|
google.charts.load('current', { packages: ['corechart', 'line'] });
|
24095
24104
|
google.charts.setOnLoadCallback(function () {
|
24096
|
-
loadQueryOrGraphTab(loadGraphResult);
|
24105
|
+
loadQueryOrGraphTab(loadGraphResult, queryErrorCallback('graph-status'));
|
24097
24106
|
});
|
24098
24107
|
|
24099
|
-
const
|
24108
|
+
const selection = getSelection();
|
24100
24109
|
focus();
|
24101
|
-
|
24110
|
+
setSelection(selection);
|
24102
24111
|
}
|
24103
24112
|
|
24104
24113
|
function selectQueryTab () {
|
@@ -24106,11 +24115,23 @@ var sqlui = (function (exports) {
|
|
24106
24115
|
selected.style.display = 'flex';
|
24107
24116
|
});
|
24108
24117
|
|
24109
|
-
const
|
24118
|
+
const selection = getSelection();
|
24110
24119
|
focus();
|
24111
|
-
|
24120
|
+
setSelection(selection);
|
24121
|
+
|
24122
|
+
loadQueryOrGraphTab(loadQueryResult, queryErrorCallback('query-status'));
|
24123
|
+
}
|
24112
24124
|
|
24113
|
-
|
24125
|
+
function queryErrorCallback (statusElementId) {
|
24126
|
+
const statusElement = document.getElementById(statusElementId);
|
24127
|
+
return function (message, error) {
|
24128
|
+
if (error) {
|
24129
|
+
console.log(`${message}\n${error}`);
|
24130
|
+
statusElement.innerText = `error: ${message} (check console)`;
|
24131
|
+
} else {
|
24132
|
+
statusElement.innerText = `error: ${message}`;
|
24133
|
+
}
|
24134
|
+
}
|
24114
24135
|
}
|
24115
24136
|
|
24116
24137
|
function selectSavedTab () {
|
@@ -24135,6 +24156,7 @@ var sqlui = (function (exports) {
|
|
24135
24156
|
}
|
24136
24157
|
saved.forEach(file => {
|
24137
24158
|
const divElement = document.createElement('div');
|
24159
|
+
divElement.classList.add('saved-list-item');
|
24138
24160
|
divElement.addEventListener('click', function (event) {
|
24139
24161
|
clearResult();
|
24140
24162
|
const url = new URL(window.location);
|
@@ -24144,7 +24166,7 @@ var sqlui = (function (exports) {
|
|
24144
24166
|
window.history.pushState({}, '', url);
|
24145
24167
|
route();
|
24146
24168
|
});
|
24147
|
-
const nameElement = document.createElement('
|
24169
|
+
const nameElement = document.createElement('h2');
|
24148
24170
|
nameElement.innerText = file.filename;
|
24149
24171
|
divElement.appendChild(nameElement);
|
24150
24172
|
|
@@ -24157,9 +24179,21 @@ var sqlui = (function (exports) {
|
|
24157
24179
|
window.savedLoaded = true;
|
24158
24180
|
}
|
24159
24181
|
|
24160
|
-
function
|
24182
|
+
function submitAll () {
|
24183
|
+
submit(null);
|
24184
|
+
}
|
24185
|
+
|
24186
|
+
function submitCurrent () {
|
24187
|
+
submit(getSelection());
|
24188
|
+
}
|
24189
|
+
|
24190
|
+
function submit (selection) {
|
24161
24191
|
const url = new URL(window.location);
|
24162
|
-
|
24192
|
+
if (selection) {
|
24193
|
+
url.searchParams.set('selection', selection.join(':'));
|
24194
|
+
} else {
|
24195
|
+
url.searchParams.delete('selection');
|
24196
|
+
}
|
24163
24197
|
|
24164
24198
|
let sql = getValue().trim();
|
24165
24199
|
sql = sql === '' ? null : sql;
|
@@ -24218,7 +24252,7 @@ var sqlui = (function (exports) {
|
|
24218
24252
|
}
|
24219
24253
|
}
|
24220
24254
|
|
24221
|
-
function fetchSql (sql,
|
24255
|
+
function fetchSql (sql, selection, successCallback, errorCallback) {
|
24222
24256
|
fetch('query', {
|
24223
24257
|
headers: {
|
24224
24258
|
Accept: 'application/json',
|
@@ -24227,40 +24261,69 @@ var sqlui = (function (exports) {
|
|
24227
24261
|
method: 'POST',
|
24228
24262
|
body: JSON.stringify({
|
24229
24263
|
sql,
|
24230
|
-
|
24264
|
+
selection
|
24231
24265
|
})
|
24232
24266
|
})
|
24233
|
-
.then((response) =>
|
24234
|
-
|
24267
|
+
.then((response) => {
|
24268
|
+
const contentType = response.headers.get('content-type');
|
24269
|
+
if (contentType && contentType.indexOf('application/json') !== -1) {
|
24270
|
+
response.json().then((result) => {
|
24271
|
+
if (result?.query) {
|
24272
|
+
successCallback(result);
|
24273
|
+
} else if (result?.error) {
|
24274
|
+
errorCallback(result.error, result.stacktrace);
|
24275
|
+
} else if (result) {
|
24276
|
+
errorCallback('failed to execute query', result.toString());
|
24277
|
+
} else {
|
24278
|
+
errorCallback('failed to execute query');
|
24279
|
+
}
|
24280
|
+
});
|
24281
|
+
} else {
|
24282
|
+
response.text().then((result) => {
|
24283
|
+
errorCallback('failed to execute query', result);
|
24284
|
+
});
|
24285
|
+
}
|
24286
|
+
})
|
24287
|
+
.catch(function (error) {
|
24288
|
+
errorCallback('failed to execute query', error.stack);
|
24289
|
+
});
|
24235
24290
|
}
|
24236
24291
|
|
24237
|
-
function fetchFile (name,
|
24292
|
+
function fetchFile (name, successCallback, errorCallback) {
|
24238
24293
|
fetch(`query_file?file=${name}`, {
|
24239
24294
|
headers: {
|
24240
24295
|
Accept: 'application/json'
|
24241
24296
|
},
|
24242
24297
|
method: 'GET'
|
24243
24298
|
})
|
24244
|
-
.then((response) =>
|
24245
|
-
|
24246
|
-
|
24247
|
-
|
24248
|
-
|
24249
|
-
|
24250
|
-
|
24251
|
-
|
24252
|
-
|
24253
|
-
|
24254
|
-
|
24255
|
-
|
24256
|
-
|
24299
|
+
.then((response) => {
|
24300
|
+
const contentType = response.headers.get('content-type');
|
24301
|
+
if (contentType && contentType.indexOf('application/json') !== -1) {
|
24302
|
+
response.json().then((result) => {
|
24303
|
+
if (result?.query) {
|
24304
|
+
successCallback(result);
|
24305
|
+
} else if (result?.error) {
|
24306
|
+
errorCallback(result.error, result.stacktrace);
|
24307
|
+
} else if (result) {
|
24308
|
+
errorCallback('failed to load file ', result.toString());
|
24309
|
+
} else {
|
24310
|
+
errorCallback('failed to load file');
|
24311
|
+
}
|
24312
|
+
});
|
24313
|
+
} else {
|
24314
|
+
errorCallback('failed to load file', response.toString());
|
24315
|
+
}
|
24316
|
+
})
|
24317
|
+
.catch(function (error) {
|
24318
|
+
errorCallback('failed to load file', error.stack);
|
24319
|
+
});
|
24257
24320
|
}
|
24258
24321
|
|
24259
|
-
function loadQueryOrGraphTab (callback) {
|
24322
|
+
function loadQueryOrGraphTab (callback, errorCallback) {
|
24260
24323
|
const params = new URLSearchParams(window.location.search);
|
24261
24324
|
const sql = params.get('sql');
|
24262
24325
|
const file = params.get('file');
|
24263
|
-
const
|
24326
|
+
const selection = params.has('selection') ? params.get('selection') : null;
|
24264
24327
|
|
24265
24328
|
if (params.has('sql') && window.result && sql === window.result.query) {
|
24266
24329
|
callback();
|
@@ -24270,7 +24333,7 @@ var sqlui = (function (exports) {
|
|
24270
24333
|
return
|
24271
24334
|
}
|
24272
24335
|
|
24273
|
-
if (params.has('file') && params.has('sql') &&
|
24336
|
+
if (params.has('file') && params.has('sql') && selection === window.result.selection) {
|
24274
24337
|
// TODO: show an error.
|
24275
24338
|
throw new Error('You can only specify a file or sql, not both.')
|
24276
24339
|
}
|
@@ -24279,24 +24342,21 @@ var sqlui = (function (exports) {
|
|
24279
24342
|
|
24280
24343
|
if (params.has('sql')) {
|
24281
24344
|
setValue(sql);
|
24282
|
-
|
24283
|
-
fetchSql(params.get('sql'), cursor, function (result) {
|
24345
|
+
fetchSql(params.get('sql'), selection, function (result) {
|
24284
24346
|
window.result = result;
|
24285
24347
|
callback();
|
24286
|
-
});
|
24348
|
+
}, errorCallback);
|
24287
24349
|
} else if (params.has('file')) {
|
24288
24350
|
setValue('');
|
24289
24351
|
fetchFile(file, function (result) {
|
24290
24352
|
window.result = result;
|
24291
|
-
|
24292
|
-
setValue(result.query);
|
24293
|
-
}
|
24353
|
+
setValue(result.query);
|
24294
24354
|
callback();
|
24295
|
-
});
|
24355
|
+
}, errorCallback);
|
24296
24356
|
}
|
24297
|
-
if (params.has('
|
24357
|
+
if (params.has('selection')) {
|
24298
24358
|
focus();
|
24299
|
-
|
24359
|
+
setSelection(params.get('selection').split(':'));
|
24300
24360
|
}
|
24301
24361
|
}
|
24302
24362
|
|
@@ -24308,9 +24368,9 @@ var sqlui = (function (exports) {
|
|
24308
24368
|
|
24309
24369
|
setQueryStatus(window.result);
|
24310
24370
|
|
24311
|
-
if (!window.result.rows) {
|
24312
|
-
|
24313
|
-
}
|
24371
|
+
// if (!window.result.rows) {
|
24372
|
+
// return
|
24373
|
+
// }
|
24314
24374
|
|
24315
24375
|
const tableElement = document.createElement('table');
|
24316
24376
|
const theadElement = document.createElement('thead');
|
@@ -24326,7 +24386,9 @@ var sqlui = (function (exports) {
|
|
24326
24386
|
template.innerHTML = `<th class="cell">${column}</th>`;
|
24327
24387
|
headerElement.appendChild(template.content.firstChild);
|
24328
24388
|
});
|
24329
|
-
|
24389
|
+
if (window.result.columns.length > 0) {
|
24390
|
+
headerElement.appendChild(document.createElement('th'));
|
24391
|
+
}
|
24330
24392
|
let highlight = false;
|
24331
24393
|
window.result.rows.forEach(function (row) {
|
24332
24394
|
const rowElement = document.createElement('tr');
|
@@ -24362,8 +24424,11 @@ var sqlui = (function (exports) {
|
|
24362
24424
|
|
24363
24425
|
window.result.rows.forEach((row) => {
|
24364
24426
|
const rowValues = row.map((value, index) => {
|
24365
|
-
if (window.result.column_types[index] === 'date') {
|
24427
|
+
if (window.result.column_types[index] === 'date' || window.result.column_types[index] === 'datetime') {
|
24366
24428
|
return new Date(value)
|
24429
|
+
} else if (window.result.column_types[index] === 'timeofday') {
|
24430
|
+
// TODO: This should be hour, minute, second, milliseconds
|
24431
|
+
return [0, 0, 0, 0]
|
24367
24432
|
} else {
|
24368
24433
|
return value
|
24369
24434
|
}
|
@@ -24387,13 +24452,6 @@ var sqlui = (function (exports) {
|
|
24387
24452
|
|
24388
24453
|
function setGraphStatus (result) {
|
24389
24454
|
const statusElement = document.getElementById('graph-status');
|
24390
|
-
if (!result.rows) {
|
24391
|
-
// TODO use a popup
|
24392
|
-
console.log('error parsing graph result');
|
24393
|
-
console.log(JSON.stringify(result, null, 2));
|
24394
|
-
statusElement.innerText = 'error, check console';
|
24395
|
-
return
|
24396
|
-
}
|
24397
24455
|
|
24398
24456
|
if (result.total_rows === 1) {
|
24399
24457
|
statusElement.innerText = `${result.total_rows} row`;
|
@@ -24408,13 +24466,6 @@ var sqlui = (function (exports) {
|
|
24408
24466
|
|
24409
24467
|
function setQueryStatus (result) {
|
24410
24468
|
const statusElement = document.getElementById('query-status');
|
24411
|
-
if (!result.rows) {
|
24412
|
-
// TODO use a popup
|
24413
|
-
console.log('error parsing query result');
|
24414
|
-
console.log(JSON.stringify(result, null, 2));
|
24415
|
-
statusElement.innerText = 'error, check console';
|
24416
|
-
return
|
24417
|
-
}
|
24418
24469
|
|
24419
24470
|
if (result.total_rows === 1) {
|
24420
24471
|
statusElement.innerText = `${result.total_rows} row`;
|
@@ -24447,23 +24498,58 @@ var sqlui = (function (exports) {
|
|
24447
24498
|
}
|
24448
24499
|
|
24449
24500
|
window.onload = function () {
|
24450
|
-
|
24451
|
-
|
24452
|
-
|
24453
|
-
|
24454
|
-
|
24455
|
-
|
24456
|
-
|
24457
|
-
|
24501
|
+
fetch('metadata', {
|
24502
|
+
headers: {
|
24503
|
+
Accept: 'application/json'
|
24504
|
+
},
|
24505
|
+
method: 'GET'
|
24506
|
+
})
|
24507
|
+
.then((response) => {
|
24508
|
+
const contentType = response.headers.get('content-type');
|
24509
|
+
if (contentType && contentType.indexOf('application/json') !== -1) {
|
24510
|
+
return response.json().then((result) => {
|
24511
|
+
if (result.error) {
|
24512
|
+
let error = `<pre>${result.error}`;
|
24513
|
+
if (result.stacktrace) {
|
24514
|
+
error += '\n' + result.stacktrace + '</pre>';
|
24515
|
+
}
|
24516
|
+
document.getElementById('loading-box').innerHTML = error;
|
24517
|
+
} else if (!result.server) {
|
24518
|
+
document.getElementById('loading-box').innerHTML = `
|
24519
|
+
<pre>
|
24520
|
+
error loading metadata, response:
|
24521
|
+
${JSON.stringify(result)}
|
24522
|
+
</pre>
|
24523
|
+
`;
|
24524
|
+
} else {
|
24525
|
+
window.metadata = result;
|
24526
|
+
document.getElementById('loading-box').style.display = 'none';
|
24527
|
+
document.getElementById('main-box').style.display = 'flex';
|
24528
|
+
document.getElementById('server-name').innerText = result.server;
|
24529
|
+
const queryElement = document.getElementById('query');
|
24458
24530
|
|
24459
|
-
|
24460
|
-
|
24531
|
+
init(queryElement, submitCurrent, submitAll);
|
24532
|
+
route();
|
24533
|
+
}
|
24534
|
+
})
|
24535
|
+
} else {
|
24536
|
+
console.log(response);
|
24537
|
+
document.getElementById('loading-box').style.display = 'flex';
|
24538
|
+
document.getElementById('main-box').style.display = 'none';
|
24539
|
+
document.getElementById('loading-box').innerHTML = `<pre>${response}</pre>`;
|
24540
|
+
}
|
24541
|
+
})
|
24542
|
+
.catch(function (error) {
|
24543
|
+
console.log(error);
|
24544
|
+
document.getElementById('loading-box').style.display = 'flex';
|
24545
|
+
document.getElementById('main-box').style.display = 'none';
|
24546
|
+
document.getElementById('loading-box').innerHTML = `<pre>${error.stack}</pre>`;
|
24461
24547
|
});
|
24462
|
-
route();
|
24463
|
-
});
|
24464
24548
|
};
|
24465
24549
|
|
24466
24550
|
exports.selectTab = selectTab;
|
24551
|
+
exports.submitAll = submitAll;
|
24552
|
+
exports.submitCurrent = submitCurrent;
|
24467
24553
|
|
24468
24554
|
return exports;
|
24469
24555
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqlui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Dower
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mysql2
|
@@ -158,10 +158,15 @@ extensions: []
|
|
158
158
|
extra_rdoc_files: []
|
159
159
|
files:
|
160
160
|
- ".version"
|
161
|
+
- app/args.rb
|
161
162
|
- app/database_config.rb
|
163
|
+
- app/database_metadata.rb
|
164
|
+
- app/deep.rb
|
162
165
|
- app/environment.rb
|
166
|
+
- app/mysql_types.rb
|
163
167
|
- app/server.rb
|
164
168
|
- app/sql_parser.rb
|
169
|
+
- app/sqlui.rb
|
165
170
|
- app/sqlui_config.rb
|
166
171
|
- app/views/databases.erb
|
167
172
|
- bin/sqlui
|