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.
@@ -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 () {
@@ -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('h1');
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 submit () {
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
- url.searchParams.set('cursor', getCursor());
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, cursor, callback) {
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
- cursor
24264
+ selection
24231
24265
  })
24232
24266
  })
24233
- .then((response) => response.json())
24234
- .then((result) => callback(result));
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, callback) {
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) => 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));
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 cursor = params.has('cursor') ? params.get('cursor') : 0;
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') && cursor === window.result.cursor) {
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
- const cursor = params.has('cursor') ? params.get('cursor') : 0;
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
- if (window.result.query) {
24292
- setValue(result.query);
24293
- }
24353
+ setValue(result.query);
24294
24354
  callback();
24295
- });
24355
+ }, errorCallback);
24296
24356
  }
24297
- if (params.has('cursor')) {
24357
+ if (params.has('selection')) {
24298
24358
  focus();
24299
- setCursor(cursor);
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
- return
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
- headerElement.appendChild(document.createElement('th'));
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
- 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');
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
- init(queryElement, function () {
24460
- submit();
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.19
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-25 00:00:00.000000000 Z
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