sqlui 0.1.18 → 0.1.20

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.
@@ -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 getCursor () {
23875
- return window.editorView.state.selection.main.head
23874
+ function getSelection () {
23875
+ return [window.editorView.state.selection.main.from, window.editorView.state.selection.main.to]
23876
23876
  }
23877
23877
 
23878
- function setCursor (cursor) {
23879
- window.editorView.dispatch({ selection: { anchor: Math.min(cursor, window.editorView.state.doc.length) } });
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
- headerTrElement.appendChild(document.createElement('th'));
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 cursor = getCursor();
24108
+ const selection = getSelection();
24100
24109
  focus();
24101
- setCursor(cursor);
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 cursor = getCursor();
24118
+ const selection = getSelection();
24110
24119
  focus();
24111
- setCursor(cursor);
24120
+ setSelection(selection);
24121
+
24122
+ loadQueryOrGraphTab(loadQueryResult, queryErrorCallback('query-status'));
24123
+ }
24112
24124
 
24113
- loadQueryOrGraphTab(loadQueryResult);
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 () {
@@ -24157,9 +24178,21 @@ var sqlui = (function (exports) {
24157
24178
  window.savedLoaded = true;
24158
24179
  }
24159
24180
 
24160
- function submit () {
24181
+ function submitAll () {
24182
+ submit(null);
24183
+ }
24184
+
24185
+ function submitCurrent () {
24186
+ submit(getSelection());
24187
+ }
24188
+
24189
+ function submit (selection) {
24161
24190
  const url = new URL(window.location);
24162
- url.searchParams.set('cursor', getCursor());
24191
+ if (selection) {
24192
+ url.searchParams.set('selection', selection.join(':'));
24193
+ } else {
24194
+ url.searchParams.delete('selection');
24195
+ }
24163
24196
 
24164
24197
  let sql = getValue().trim();
24165
24198
  sql = sql === '' ? null : sql;
@@ -24218,7 +24251,7 @@ var sqlui = (function (exports) {
24218
24251
  }
24219
24252
  }
24220
24253
 
24221
- function fetchSql (sql, cursor, callback) {
24254
+ function fetchSql (sql, selection, successCallback, errorCallback) {
24222
24255
  fetch('query', {
24223
24256
  headers: {
24224
24257
  Accept: 'application/json',
@@ -24227,40 +24260,69 @@ var sqlui = (function (exports) {
24227
24260
  method: 'POST',
24228
24261
  body: JSON.stringify({
24229
24262
  sql,
24230
- cursor
24263
+ selection
24231
24264
  })
24232
24265
  })
24233
- .then((response) => response.json())
24234
- .then((result) => callback(result));
24266
+ .then((response) => {
24267
+ const contentType = response.headers.get('content-type');
24268
+ if (contentType && contentType.indexOf('application/json') !== -1) {
24269
+ response.json().then((result) => {
24270
+ if (result?.query) {
24271
+ successCallback(result);
24272
+ } else if (result?.error) {
24273
+ errorCallback(result.error, result.stacktrace);
24274
+ } else if (result) {
24275
+ errorCallback('failed to execute query', result.toString());
24276
+ } else {
24277
+ errorCallback('failed to execute query');
24278
+ }
24279
+ });
24280
+ } else {
24281
+ response.text().then((result) => {
24282
+ errorCallback('failed to execute query', result);
24283
+ });
24284
+ }
24285
+ })
24286
+ .catch(function (error) {
24287
+ errorCallback('failed to execute query', error.stack);
24288
+ });
24235
24289
  }
24236
24290
 
24237
- function fetchFile (name, callback) {
24291
+ function fetchFile (name, successCallback, errorCallback) {
24238
24292
  fetch(`query_file?file=${name}`, {
24239
24293
  headers: {
24240
24294
  Accept: 'application/json'
24241
24295
  },
24242
24296
  method: 'GET'
24243
24297
  })
24244
- .then((response) => response.json())
24245
- .then((result) => callback(result));
24246
- }
24247
-
24248
- function fetchMetadata (callback) {
24249
- fetch('metadata', {
24250
- headers: {
24251
- Accept: 'application/json'
24252
- },
24253
- method: 'GET'
24254
- })
24255
- .then((response) => response.json())
24256
- .then((result) => callback(result));
24298
+ .then((response) => {
24299
+ const contentType = response.headers.get('content-type');
24300
+ if (contentType && contentType.indexOf('application/json') !== -1) {
24301
+ response.json().then((result) => {
24302
+ if (result?.query) {
24303
+ successCallback(result);
24304
+ } else if (result?.error) {
24305
+ errorCallback(result.error, result.stacktrace);
24306
+ } else if (result) {
24307
+ errorCallback('failed to load file ', result.toString());
24308
+ } else {
24309
+ errorCallback('failed to load file');
24310
+ }
24311
+ });
24312
+ } else {
24313
+ errorCallback('failed to load file', response.toString());
24314
+ }
24315
+ })
24316
+ .catch(function (error) {
24317
+ errorCallback('failed to load file', error.stack);
24318
+ });
24257
24319
  }
24258
24320
 
24259
- function loadQueryOrGraphTab (callback) {
24321
+ function loadQueryOrGraphTab (callback, errorCallback) {
24260
24322
  const params = new URLSearchParams(window.location.search);
24261
24323
  const sql = params.get('sql');
24262
24324
  const file = params.get('file');
24263
- const cursor = params.has('cursor') ? params.get('cursor') : 0;
24325
+ const selection = params.has('selection') ? params.get('selection') : null;
24264
24326
 
24265
24327
  if (params.has('sql') && window.result && sql === window.result.query) {
24266
24328
  callback();
@@ -24270,7 +24332,7 @@ var sqlui = (function (exports) {
24270
24332
  return
24271
24333
  }
24272
24334
 
24273
- if (params.has('file') && params.has('sql') && cursor === window.result.cursor) {
24335
+ if (params.has('file') && params.has('sql') && selection === window.result.selection) {
24274
24336
  // TODO: show an error.
24275
24337
  throw new Error('You can only specify a file or sql, not both.')
24276
24338
  }
@@ -24279,24 +24341,21 @@ var sqlui = (function (exports) {
24279
24341
 
24280
24342
  if (params.has('sql')) {
24281
24343
  setValue(sql);
24282
- const cursor = params.has('cursor') ? params.get('cursor') : 0;
24283
- fetchSql(params.get('sql'), cursor, function (result) {
24344
+ fetchSql(params.get('sql'), selection, function (result) {
24284
24345
  window.result = result;
24285
24346
  callback();
24286
- });
24347
+ }, errorCallback);
24287
24348
  } else if (params.has('file')) {
24288
24349
  setValue('');
24289
24350
  fetchFile(file, function (result) {
24290
24351
  window.result = result;
24291
- if (window.result.query) {
24292
- setValue(result.query);
24293
- }
24352
+ setValue(result.query);
24294
24353
  callback();
24295
- });
24354
+ }, errorCallback);
24296
24355
  }
24297
- if (params.has('cursor')) {
24356
+ if (params.has('selection')) {
24298
24357
  focus();
24299
- setCursor(cursor);
24358
+ setSelection(params.get('selection').split(':'));
24300
24359
  }
24301
24360
  }
24302
24361
 
@@ -24308,9 +24367,9 @@ var sqlui = (function (exports) {
24308
24367
 
24309
24368
  setQueryStatus(window.result);
24310
24369
 
24311
- if (!window.result.rows) {
24312
- return
24313
- }
24370
+ // if (!window.result.rows) {
24371
+ // return
24372
+ // }
24314
24373
 
24315
24374
  const tableElement = document.createElement('table');
24316
24375
  const theadElement = document.createElement('thead');
@@ -24326,7 +24385,9 @@ var sqlui = (function (exports) {
24326
24385
  template.innerHTML = `<th class="cell">${column}</th>`;
24327
24386
  headerElement.appendChild(template.content.firstChild);
24328
24387
  });
24329
- headerElement.appendChild(document.createElement('th'));
24388
+ if (window.result.columns.length > 0) {
24389
+ headerElement.appendChild(document.createElement('th'));
24390
+ }
24330
24391
  let highlight = false;
24331
24392
  window.result.rows.forEach(function (row) {
24332
24393
  const rowElement = document.createElement('tr');
@@ -24362,8 +24423,11 @@ var sqlui = (function (exports) {
24362
24423
 
24363
24424
  window.result.rows.forEach((row) => {
24364
24425
  const rowValues = row.map((value, index) => {
24365
- if (window.result.column_types[index] === 'date') {
24426
+ if (window.result.column_types[index] === 'date' || window.result.column_types[index] === 'datetime') {
24366
24427
  return new Date(value)
24428
+ } else if (window.result.column_types[index] === 'timeofday') {
24429
+ // TODO: This should be hour, minute, second, milliseconds
24430
+ return [0, 0, 0, 0]
24367
24431
  } else {
24368
24432
  return value
24369
24433
  }
@@ -24387,13 +24451,6 @@ var sqlui = (function (exports) {
24387
24451
 
24388
24452
  function setGraphStatus (result) {
24389
24453
  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
24454
 
24398
24455
  if (result.total_rows === 1) {
24399
24456
  statusElement.innerText = `${result.total_rows} row`;
@@ -24408,13 +24465,6 @@ var sqlui = (function (exports) {
24408
24465
 
24409
24466
  function setQueryStatus (result) {
24410
24467
  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
24468
 
24419
24469
  if (result.total_rows === 1) {
24420
24470
  statusElement.innerText = `${result.total_rows} row`;
@@ -24447,23 +24497,58 @@ var sqlui = (function (exports) {
24447
24497
  }
24448
24498
 
24449
24499
  window.onload = function () {
24450
- fetchMetadata(function (result) {
24451
- window.metadata = result;
24452
- if (!result.server) {
24453
- // TODO show error
24454
- throw new Error('unexpected metadata response')
24455
- }
24456
- document.getElementById('header').innerText = result.server;
24457
- const queryElement = document.getElementById('query');
24500
+ fetch('metadata', {
24501
+ headers: {
24502
+ Accept: 'application/json'
24503
+ },
24504
+ method: 'GET'
24505
+ })
24506
+ .then((response) => {
24507
+ const contentType = response.headers.get('content-type');
24508
+ if (contentType && contentType.indexOf('application/json') !== -1) {
24509
+ return response.json().then((result) => {
24510
+ if (result.error) {
24511
+ let error = `<pre>${result.error}`;
24512
+ if (result.stacktrace) {
24513
+ error += '\n' + result.stacktrace + '</pre>';
24514
+ }
24515
+ document.getElementById('loading-box').innerHTML = error;
24516
+ } else if (!result.server) {
24517
+ document.getElementById('loading-box').innerHTML = `
24518
+ <pre>
24519
+ error loading metadata, response:
24520
+ ${JSON.stringify(result)}
24521
+ </pre>
24522
+ `;
24523
+ } else {
24524
+ window.metadata = result;
24525
+ document.getElementById('loading-box').style.display = 'none';
24526
+ document.getElementById('main-box').style.display = 'flex';
24527
+ document.getElementById('server-name').innerText = result.server;
24528
+ const queryElement = document.getElementById('query');
24458
24529
 
24459
- init(queryElement, function () {
24460
- submit();
24530
+ init(queryElement, submitCurrent, submitAll);
24531
+ route();
24532
+ }
24533
+ })
24534
+ } else {
24535
+ console.log(response);
24536
+ document.getElementById('loading-box').style.display = 'flex';
24537
+ document.getElementById('main-box').style.display = 'none';
24538
+ document.getElementById('loading-box').innerHTML = `<pre>${response}</pre>`;
24539
+ }
24540
+ })
24541
+ .catch(function (error) {
24542
+ console.log(error);
24543
+ document.getElementById('loading-box').style.display = 'flex';
24544
+ document.getElementById('main-box').style.display = 'none';
24545
+ document.getElementById('loading-box').innerHTML = `<pre>${error.stack}</pre>`;
24461
24546
  });
24462
- route();
24463
- });
24464
24547
  };
24465
24548
 
24466
24549
  exports.selectTab = selectTab;
24550
+ exports.submitAll = submitAll;
24551
+ exports.submitCurrent = submitCurrent;
24467
24552
 
24468
24553
  return exports;
24469
24554
 
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.18
4
+ version: 0.1.20
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-24 00:00:00.000000000 Z
11
+ date: 2022-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mysql2
@@ -158,9 +158,16 @@ extensions: []
158
158
  extra_rdoc_files: []
159
159
  files:
160
160
  - ".version"
161
+ - app/args.rb
162
+ - app/database_config.rb
163
+ - app/database_metadata.rb
164
+ - app/deep.rb
161
165
  - app/environment.rb
166
+ - app/mysql_types.rb
162
167
  - app/server.rb
168
+ - app/sql_parser.rb
163
169
  - app/sqlui.rb
170
+ - app/sqlui_config.rb
164
171
  - app/views/databases.erb
165
172
  - bin/sqlui
166
173
  - client/resources/sqlui.css