sqlui 0.1.56 → 0.1.58

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54098affe9aed43da3e5cfb8ac348989f4965f790ecdfec200ec9e79d3b7b532
4
- data.tar.gz: cd5b2dea4f9f7afc1a465e6c6d68f8e84982547032e90fd5f979c4f6f72eb452
3
+ metadata.gz: e0a7dab933454e7e153894eb7e0317680dd1f4aa88953480b31d94a825f95f10
4
+ data.tar.gz: 6cf9998337f955912eb5a050dfd024bee292afef191a2ee639cda5552e86490c
5
5
  SHA512:
6
- metadata.gz: 9444bf4a2cb0bb5d9f397d2ed6ad0ef212846db09172314083f7f951f3a1e58ec9965f1b6f08432ce74739cdf7e35b7d112b4ba0a4c9a5c62abdb7763e8c371a
7
- data.tar.gz: c37479f67876f510a7a6c65c72bf4abbb7c0eeb7bd3b82fc6f0571f91a369685db75b177b50db7b95a533254c40a769248b588d79b41cd79fd475a26d6999c14
6
+ metadata.gz: f0da91f85d1880eec8ef7d99e5858c49f61334dbabf7d8286b226f34ff9984d5faf30eb4c1be59ea810c4f45e7a148782eadd5d0fb4c488c96403d96d6257b84
7
+ data.tar.gz: b1da77e8601b4a7c48bedadcb6e513ef7729893eaad9e30232d1dadb1d600d5ad6f127c28726eb009bbc6abc274369b1fe99d611dc69dae3d353db00c3ea4f59
data/.release-version CHANGED
@@ -1 +1 @@
1
- 0.1.56
1
+ 0.1.58
data/app/server.rb CHANGED
@@ -138,13 +138,13 @@ class Server < Sinatra::Base
138
138
  break client_error('missing sql') unless params[:sql]
139
139
 
140
140
  variables = params[:variables] || {}
141
- sql = find_selected_query(params[:sql], params[:selection])
141
+ queries = find_selected_queries(params[:sql], params[:selection])
142
142
 
143
143
  status 200
144
144
  headers 'Content-Type' => 'application/json; charset=utf-8'
145
145
 
146
146
  database.with_client do |client|
147
- query_result = execute_query(client, variables, sql)
147
+ query_result = execute_query(client, variables, queries)
148
148
  stream do |out|
149
149
  if query_result
150
150
  json = <<~RES.chomp
@@ -159,7 +159,7 @@ class Server < Sinatra::Base
159
159
  out << json
160
160
  bytes = json.bytesize
161
161
  query_result.each_with_index do |row, i|
162
- json = "#{i.zero? ? '' : ','}\n #{row.to_json}"
162
+ json = "#{i.zero? ? '' : ','}\n #{row.map { |v| big_decimal_to_float(v) }.to_json}"
163
163
  bytes += json.bytesize
164
164
  break if i == Sqlui::MAX_ROWS || bytes > Sqlui::MAX_BYTES
165
165
 
@@ -191,7 +191,7 @@ class Server < Sinatra::Base
191
191
 
192
192
  sql = Base64.decode64(params[:sql]).force_encoding('UTF-8')
193
193
  variables = params.map { |k, v| k[0] == '_' ? [k, v] : nil }.compact.to_h
194
- sql = find_selected_query(sql, params[:selection])
194
+ queries = find_selected_queries(sql, params[:selection])
195
195
 
196
196
  content_type 'application/csv; charset=utf-8'
197
197
  headers 'Cache-Control' => 'no-cache'
@@ -199,11 +199,11 @@ class Server < Sinatra::Base
199
199
  status 200
200
200
 
201
201
  database.with_client do |client|
202
- query_result = execute_query(client, variables, sql)
202
+ query_result = execute_query(client, variables, queries)
203
203
  stream do |out|
204
204
  out << CSV::Row.new(query_result.fields, query_result.fields, header_row: true).to_s.strip
205
205
  query_result.each do |row|
206
- out << "\n#{CSV::Row.new(query_result.fields, row).to_s.strip}"
206
+ out << "\n#{CSV::Row.new(query_result.fields, row.map { |v| big_decimal_to_float(v) }).to_s.strip}"
207
207
  end
208
208
  end
209
209
  end
@@ -250,33 +250,45 @@ class Server < Sinatra::Base
250
250
  body({ error: message, stacktrace: stacktrace }.compact.to_json)
251
251
  end
252
252
 
253
- def find_selected_query(full_sql, selection)
254
- return full_sql unless selection
255
-
256
- if selection.include?('-')
257
- # sort because the selection could be in either direction
258
- selection = selection.split('-').map { |v| Integer(v) }.sort
259
- else
260
- selection = Integer(selection)
261
- selection = [selection, selection]
262
- end
253
+ def find_selected_queries(full_sql, selection)
254
+ if selection
255
+ if selection.include?('-')
256
+ # sort because the selection could be in either direction
257
+ selection = selection.split('-').map { |v| Integer(v) }.sort
258
+ else
259
+ selection = Integer(selection)
260
+ selection = [selection, selection]
261
+ end
263
262
 
264
- if selection[0] == selection[1]
265
- SqlParser.find_statement_at_cursor(full_sql, selection[0])
263
+ if selection[0] == selection[1]
264
+ [SqlParser.find_statement_at_cursor(full_sql, selection[0])]
265
+ else
266
+ SqlParser.split(full_sql[selection[0], selection[1]])
267
+ end
266
268
  else
267
- full_sql[selection[0], selection[1]]
269
+ SqlParser.split(full_sql)
268
270
  end
269
271
  end
270
272
 
271
- def execute_query(client, variables, sql)
273
+ def execute_query(client, variables, queries)
272
274
  variables.each do |name, value|
273
275
  client.query("SET @#{name} = #{value};")
274
276
  end
275
- queries = if sql.include?(';')
276
- sql.split(/(?<=;)/).map(&:strip).reject(&:empty?)
277
- else
278
- [sql]
279
- end
280
277
  queries.map { |current| client.query(current) }.last
281
278
  end
279
+
280
+ def big_decimal_to_float(maybe_big_decimal)
281
+ # TODO: This BigDecimal thing needs some thought.
282
+ if maybe_big_decimal.is_a?(BigDecimal)
283
+ big_decimal_string = maybe_big_decimal.to_s('F')
284
+ float = maybe_big_decimal.to_f
285
+ if big_decimal_string == float.to_s
286
+ float
287
+ else
288
+ big_decimal_string
289
+ end
290
+ else
291
+ maybe_big_decimal
292
+ end
293
+ end
282
294
  end
data/app/sql_parser.rb CHANGED
@@ -12,6 +12,10 @@ class SqlParser
12
12
  part_with_range[0]
13
13
  end
14
14
 
15
+ def self.split(sql)
16
+ parse(sql).map(&:first)
17
+ end
18
+
15
19
  def self.parse(sql)
16
20
  scanner = StringScanner.new(sql)
17
21
  statements = []
data/app/sqlui.rb CHANGED
@@ -6,8 +6,8 @@ require_relative 'version'
6
6
 
7
7
  # Main entry point.
8
8
  class Sqlui
9
- MAX_ROWS = 5_000
10
- MAX_BYTES = 10 * 1_024 * 1_024
9
+ MAX_ROWS = 50_000
10
+ MAX_BYTES = 10 * 1_024 * 1_024 # 10 MB
11
11
 
12
12
  def initialize(config_file)
13
13
  raise 'you must specify a configuration file' unless config_file
data/app/views/sqlui.erb CHANGED
@@ -100,8 +100,10 @@
100
100
  <div style="flex: 1;"></div>
101
101
  <div id="pagination-box" class="tab-content-element">
102
102
  <div id="page-count-box"></div>
103
+ <input id="first-button" class="pagination-button" type="button" value="First" />
103
104
  <input id="prev-button" class="pagination-button" type="button" value="Prev" />
104
105
  <input id="next-button" class="pagination-button" type="button" value="Next" />
106
+ <input id="last-button" class="pagination-button" type="button" value="Last" />
105
107
  </div>
106
108
  </div>
107
109
  </div>
@@ -228,7 +228,7 @@ p {
228
228
  background: none !important;
229
229
  }
230
230
 
231
- .status-message {
231
+ #status-message {
232
232
  display: flex;
233
233
  justify-content: center;
234
234
  align-content: center;
@@ -282,7 +282,6 @@ table {
282
282
  border-spacing: 0;
283
283
  color: #333;
284
284
  font-size: 18px;
285
- width: 100%;
286
285
  }
287
286
 
288
287
  table td:last-child, table th:last-child {
@@ -295,6 +294,10 @@ td, th {
295
294
  max-width: 500px;
296
295
  }
297
296
 
297
+ td:last-child, th:last-child {
298
+ max-width: none;
299
+ }
300
+
298
301
  td {
299
302
  overflow: hidden;
300
303
  text-overflow: ellipsis;
@@ -490,15 +493,8 @@ select {
490
493
  font-size: 16px;
491
494
  }
492
495
 
493
- #next-button {
494
-
495
- }
496
-
497
- #prev-button {
498
- margin: 0 10px;
499
- }
500
-
501
496
  .pagination-button {
497
+ margin: 0 10px;
502
498
  cursor: pointer;
503
499
  background: none;
504
500
  color: #333;
@@ -24296,48 +24296,51 @@
24296
24296
  }
24297
24297
 
24298
24298
  class Drag {
24299
+ tableElement = null
24299
24300
  scrolled = null
24300
24301
  scrollOffset = null
24301
24302
  containerOffset = null
24302
24303
  containerWidth = null
24303
24304
  thElement = null
24304
24305
  colElement = null
24305
- otherColWidths = null
24306
+ otherColsWidth = null
24306
24307
  lastColElement = null
24307
24308
  }
24308
24309
 
24309
24310
  let drag = new Drag();
24310
24311
 
24311
24312
  document.addEventListener('mousedown', (event) => {
24312
- if (event.target.classList.contains('col-resizer')) {
24313
- drag = new Drag();
24314
- event.preventDefault();
24315
- const thElement = event.target.parentElement.parentElement;
24316
- if (thElement.tagName.toLowerCase() !== 'th') {
24317
- throw new Error(`expected th element, found: ${thElement}`)
24318
- }
24319
- const trElement = thElement.parentElement;
24320
- const theadElement = trElement.parentElement;
24321
- const tableElement = theadElement.parentElement;
24322
- const containerElement = tableElement.parentElement;
24323
- drag.containerWidth = containerElement.clientWidth;
24324
- drag.scrollOffset = containerElement.scrollLeft;
24325
- drag.scrolled = drag.scrollOffset > 0;
24326
- drag.containerOffset = containerElement.offsetLeft;
24327
- drag.thElement = thElement;
24328
- drag.colElement = document.getElementById(event.target.dataset.colId);
24329
-
24330
- const colElements = Array.from(drag.colElement.parentElement.childNodes);
24331
- drag.lastColElement = colElements[colElements.length - 1];
24332
- drag.otherColsWidth = 0;
24333
- for (let i = 0; i < colElements.length - 1; i++) {
24334
- if (colElements[i] !== drag.colElement) {
24335
- drag.otherColsWidth += colElements[i].getBoundingClientRect().width;
24336
- }
24337
- colElements[i].style.width = `${colElements[i].getBoundingClientRect().width}px`;
24338
- }
24339
- tableElement.style.tableLayout = 'fixed';
24313
+ if (!event.target.classList.contains('col-resizer')) return
24314
+
24315
+ drag = new Drag();
24316
+ event.preventDefault();
24317
+ const thElement = event.target.parentElement.parentElement;
24318
+ if (thElement.tagName.toLowerCase() !== 'th') {
24319
+ throw new Error(`expected th element, found: ${thElement}`)
24320
+ }
24321
+ const trElement = thElement.parentElement;
24322
+ const theadElement = trElement.parentElement;
24323
+ const tableElement = theadElement.parentElement;
24324
+ const containerElement = tableElement.parentElement;
24325
+ drag.tableElement = tableElement;
24326
+ drag.containerWidth = containerElement.clientWidth;
24327
+ drag.scrollOffset = containerElement.scrollLeft;
24328
+ drag.scrolled = drag.scrollOffset > 0;
24329
+ drag.containerOffset = containerElement.offsetLeft;
24330
+ drag.thElement = thElement;
24331
+ drag.colElement = tableElement.querySelector(`col[data-col-id=${event.target.dataset.colId}]`);
24332
+
24333
+ const colElements = Array.from(drag.colElement.parentElement.childNodes);
24334
+ drag.lastColElement = colElements[colElements.length - 1];
24335
+ drag.otherColsWidth = 0;
24336
+ for (let i = 0; i < colElements.length; i++) {
24337
+ if (colElements[i] !== drag.colElement && i !== (colElements.length - 1)) {
24338
+ drag.otherColsWidth += colElements[i].getBoundingClientRect().width;
24339
+ }
24340
+ colElements[i].style.width = `${colElements[i].getBoundingClientRect().width}px`;
24340
24341
  }
24342
+ tableElement.style.tableLayout = 'fixed';
24343
+ tableElement.style.width = `${tableElement.getBoundingClientRect().width}px`;
24341
24344
  });
24342
24345
 
24343
24346
  document.addEventListener('mouseup', (event) => {
@@ -24351,134 +24354,156 @@
24351
24354
  if (newColumnWidth < drag.colElement.getBoundingClientRect().width && newColumnWidth < 30) return
24352
24355
 
24353
24356
  drag.colElement.style.width = `${newColumnWidth}px`;
24357
+ drag.tableElement.columnsWidth = newColumnWidth + drag.otherColsWidth;
24358
+ let lastColWidth;
24354
24359
  if (drag.scrolled) {
24355
- drag.lastColElement.style.width = ((drag.scrollOffset + drag.containerWidth) - (newColumnWidth + drag.otherColsWidth)) + 'px';
24360
+ lastColWidth = (drag.scrollOffset + drag.containerWidth) - (drag.tableElement.columnsWidth);
24356
24361
  } else {
24357
- drag.lastColElement.style.width = (Math.max(10, drag.containerWidth - (newColumnWidth + drag.otherColsWidth))) + 'px';
24362
+ lastColWidth = Math.max(10, drag.containerWidth - (drag.tableElement.columnsWidth));
24358
24363
  }
24364
+ drag.lastColElement.style.width = lastColWidth + 'px';
24365
+ drag.tableElement.style.width = (drag.otherColsWidth + newColumnWidth + lastColWidth) + 'px';
24359
24366
  });
24360
24367
 
24361
- function createTable (containerElement, columns, rows, id, cellRenderer) {
24362
- if (!containerElement) throw new Error('missing table containerElement')
24363
- if (!columns) throw new Error('missing table columns')
24364
- if (!rows) throw new Error('missing table rows')
24365
- if (!id) throw new Error('missing table id')
24368
+ class ResizeTable extends HTMLTableElement {
24369
+ constructor (columns, rows, cellRenderer) {
24370
+ super();
24366
24371
 
24367
- const tableElement = document.createElement('table');
24368
- containerElement.appendChild(tableElement);
24369
- if (id) tableElement.id = id;
24370
- tableElement.style.tableLayout = 'auto';
24372
+ this.columns = columns;
24373
+ this.cellRenderer = cellRenderer;
24371
24374
 
24372
- const colgroupElement = document.createElement('colgroup');
24373
- tableElement.appendChild(colgroupElement);
24375
+ this.style.tableLayout = 'auto';
24376
+ this.style.width = '100%';
24374
24377
 
24375
- const theadElement = document.createElement('thead');
24376
- tableElement.appendChild(theadElement);
24378
+ const colgroupElement = document.createElement('colgroup');
24379
+ this.appendChild(colgroupElement);
24377
24380
 
24378
- const headerTrElement = document.createElement('tr');
24379
- theadElement.appendChild(headerTrElement);
24381
+ const theadElement = document.createElement('thead');
24382
+ this.appendChild(theadElement);
24380
24383
 
24381
- if (columns.length > 0) {
24382
- const colElements = [];
24383
- columns.forEach(function (column, index) {
24384
- const headerElement = document.createElement('th');
24385
- headerTrElement.appendChild(headerElement);
24384
+ const headerTrElement = document.createElement('tr');
24385
+ theadElement.appendChild(headerTrElement);
24386
24386
 
24387
- const contentWrapperElement = document.createElement('div');
24388
- contentWrapperElement.classList.add('col-content-wrapper');
24389
- headerElement.appendChild(contentWrapperElement);
24387
+ if (columns.length > 0) {
24388
+ const colElements = [];
24389
+ columns.forEach(function (column, index) {
24390
+ const headerElement = document.createElement('th');
24391
+ headerTrElement.appendChild(headerElement);
24390
24392
 
24391
- const nameElement = document.createElement('div');
24392
- nameElement.classList.add('col-name');
24393
- contentWrapperElement.appendChild(nameElement);
24393
+ const contentWrapperElement = document.createElement('div');
24394
+ contentWrapperElement.classList.add('col-content-wrapper');
24395
+ headerElement.appendChild(contentWrapperElement);
24394
24396
 
24395
- const colElement = document.createElement('col');
24396
- colElement.id = `${id}-col-${index}`;
24397
- colgroupElement.appendChild(colElement);
24398
- colElements.push(colElement);
24397
+ const nameElement = document.createElement('div');
24398
+ nameElement.classList.add('col-name');
24399
+ contentWrapperElement.appendChild(nameElement);
24399
24400
 
24400
- const resizerElement = document.createElement('div');
24401
- resizerElement.classList.add('col-resizer');
24402
- resizerElement.dataset.colId = colElement.id;
24403
- contentWrapperElement.appendChild(resizerElement);
24401
+ const colElement = document.createElement('col');
24402
+ colElement.dataset.colId = `col-${index}`;
24403
+ colgroupElement.appendChild(colElement);
24404
+ colElements.push(colElement);
24404
24405
 
24405
- nameElement.innerText = column;
24406
- });
24406
+ const resizerElement = document.createElement('div');
24407
+ resizerElement.classList.add('col-resizer');
24408
+ resizerElement.dataset.colId = colElement.dataset.colId;
24409
+ contentWrapperElement.appendChild(resizerElement);
24407
24410
 
24408
- headerTrElement.appendChild(document.createElement('th'));
24409
- const lastColElement = document.createElement('col');
24410
- lastColElement.style.width = '100%';
24411
- colElements.push(lastColElement);
24411
+ nameElement.innerText = column;
24412
+ });
24412
24413
 
24413
- let columnsWidth;
24414
- function resize () {
24415
- if (tableElement.style.tableLayout === 'auto') {
24416
- return
24417
- }
24418
- if (!columnsWidth) {
24419
- columnsWidth = 0;
24420
- colElements.slice(0, -1).forEach((element, index) => {
24421
- columnsWidth += element.getBoundingClientRect().width;
24422
- });
24423
- }
24424
- const remainingWidth = Math.max(10, containerElement.clientWidth - columnsWidth);
24425
- colElements.slice(-1)[0].style.width = `${remainingWidth}px`;
24426
- tableElement.style.width = `${columnsWidth + remainingWidth}px`;
24427
- }
24414
+ headerTrElement.appendChild(document.createElement('th'));
24415
+ const lastColElement = document.createElement('col');
24416
+ lastColElement.style.width = '100%';
24417
+ colElements.push(lastColElement);
24428
24418
 
24429
- const resizeObserver = new ResizeObserver(resize);
24430
- resizeObserver.observe(containerElement);
24419
+ const containerMutationObserver = new MutationObserver(function (mutationList, observer) {
24420
+ mutationList.forEach(function (mutation) {
24421
+ if (this.parentElement) {
24422
+ if (this.parentElement !== mutation.target) {
24423
+ throw new Error('Unexpected table parent')
24424
+ }
24425
+ return
24426
+ }
24431
24427
 
24432
- const mutationObserver = new MutationObserver((mutationList, observer) => {
24433
- if (!tableElement.parentElement) {
24434
- resizeObserver.unobserve(containerElement);
24435
- resizeObserver.unobserve(containerElement);
24436
- observer.disconnect();
24437
- }
24438
- });
24439
- mutationObserver.observe(containerElement, { childList: true });
24440
- colgroupElement.appendChild(lastColElement);
24428
+ if (observer.resizeObserver) {
24429
+ observer.resizeObserver.unobserve(mutation.target);
24430
+ observer.resizeObserver = null;
24431
+ }
24432
+ observer.disconnect();
24433
+ }.bind(this));
24434
+ }.bind(this));
24441
24435
 
24442
- setTableBody(rows, tableElement, cellRenderer);
24443
- }
24436
+ const tableResizeObserver = new ResizeObserver(function () {
24437
+ if (!this.parentElement) {
24438
+ this.observingContainer = false;
24439
+ return
24440
+ }
24441
+ if (this.observingContainer) {
24442
+ return
24443
+ }
24444
+ this.observingContainer = true;
24444
24445
 
24445
- return tableElement
24446
- }
24446
+ const containerResizeObserver = new ResizeObserver(function () {
24447
+ if (this.style.tableLayout === 'auto') return
24448
+ if (this.parentElement.scrollLeft > 0) return
24449
+ if (!this.columnsWidth) throw new Error('columnsWidth not set')
24447
24450
 
24448
- function getTableBody (tableElement) {
24449
- return tableElement.getElementsByTagName('tbody')[0]
24450
- }
24451
+ const remainingWidth = Math.max(10, this.parentElement.clientWidth - this.columnsWidth);
24452
+ colElements.slice(-1)[0].style.width = `${remainingWidth}px`;
24453
+ this.style.width = `${this.columnsWidth + remainingWidth}px`;
24454
+ }.bind(this));
24455
+ containerResizeObserver.observe(this.parentElement);
24451
24456
 
24452
- function setTableBody (rows, tableElement, cellRenderer) {
24453
- tableElement.style.tableLayout = 'auto';
24457
+ containerMutationObserver.resizeObserver = containerResizeObserver;
24458
+ containerMutationObserver.containerElement = this.parentElement;
24459
+ console.log('observing');
24460
+ console.log(this.parentElement);
24461
+ containerMutationObserver.observe(this.parentElement, { childList: true });
24462
+ }.bind(this));
24463
+ tableResizeObserver.observe(this);
24454
24464
 
24455
- let tbodyElement = getTableBody(tableElement);
24456
- tbodyElement?.parentElement?.removeChild(tbodyElement);
24465
+ colgroupElement.appendChild(lastColElement);
24457
24466
 
24458
- tbodyElement = document.createElement('tbody');
24459
- tableElement.appendChild(tbodyElement);
24460
-
24461
- let highlight = false;
24462
- rows.forEach(function (row) {
24463
- const rowElement = document.createElement('tr');
24464
- if (highlight) {
24465
- rowElement.classList.add('highlighted-row');
24467
+ this.updateTableBody(rows, cellRenderer);
24466
24468
  }
24467
- highlight = !highlight;
24468
- tbodyElement.appendChild(rowElement);
24469
- row.forEach(function (value, index) {
24470
- if (cellRenderer) {
24471
- cellRenderer(rowElement, index, value);
24472
- } else {
24473
- const cellElement = document.createElement('td');
24474
- cellElement.innerText = value;
24475
- rowElement.appendChild(cellElement);
24469
+ }
24470
+
24471
+ updateTableBody (rows, cellRenderer) {
24472
+ this.style.tableLayout = 'auto';
24473
+
24474
+ if (this.tbodyElement) this.removeChild(this.tbodyElement);
24475
+ const tbodyElement = document.createElement('tbody');
24476
+ this.appendChild(tbodyElement);
24477
+ this.tbodyElement = tbodyElement;
24478
+
24479
+ let highlight = false;
24480
+ rows.forEach(function (row) {
24481
+ const rowElement = document.createElement('tr');
24482
+ if (highlight) {
24483
+ rowElement.classList.add('highlighted-row');
24476
24484
  }
24485
+ highlight = !highlight;
24486
+ tbodyElement.appendChild(rowElement);
24487
+ row.forEach(function (value, index) {
24488
+ if (cellRenderer) {
24489
+ cellRenderer(rowElement, index, value);
24490
+ } else {
24491
+ const cellElement = document.createElement('td');
24492
+ cellElement.innerText = value;
24493
+ rowElement.appendChild(cellElement);
24494
+ }
24495
+ });
24496
+ rowElement.appendChild(document.createElement('td'));
24477
24497
  });
24478
- rowElement.appendChild(document.createElement('td'));
24479
- });
24498
+ }
24499
+
24500
+ getTableBody () {
24501
+ return this.tbodyElement
24502
+ }
24480
24503
  }
24481
24504
 
24505
+ customElements.define('resize-table', ResizeTable, { extends: 'table' });
24506
+
24482
24507
  /* global google */
24483
24508
 
24484
24509
  const PAGE_SIZE = 500;
@@ -24548,6 +24573,10 @@
24548
24573
  copyTextToClipboard(toTsv(window.sqlFetch.result.columns, window.sqlFetch.result.rows));
24549
24574
  }
24550
24575
  });
24576
+ addClickListener(document.getElementById('first-button'), (event) => {
24577
+ window.sqlFetch.page = 0;
24578
+ displaySqlFetch(window.sqlFetch);
24579
+ });
24551
24580
  addClickListener(document.getElementById('prev-button'), (event) => {
24552
24581
  window.sqlFetch.page -= 1;
24553
24582
  displaySqlFetch(window.sqlFetch);
@@ -24556,6 +24585,10 @@
24556
24585
  window.sqlFetch.page += 1;
24557
24586
  displaySqlFetch(window.sqlFetch);
24558
24587
  });
24588
+ addClickListener(document.getElementById('last-button'), (event) => {
24589
+ window.sqlFetch.page = window.sqlFetch.pageCount - 1;
24590
+ displaySqlFetch(window.sqlFetch);
24591
+ });
24559
24592
  addClickListener(document.getElementById('submit-dropdown-button-download-csv'), () => {
24560
24593
  if (!window.sqlFetch?.result) return
24561
24594
 
@@ -24811,7 +24844,7 @@
24811
24844
  cellElement.innerText = value;
24812
24845
  rowElement.appendChild(cellElement);
24813
24846
  };
24814
- createTable(columnsElement, columns, rows, 'columns-table', cellRenderer);
24847
+ columnsElement.appendChild(new ResizeTable(columns, rows, cellRenderer));
24815
24848
  }
24816
24849
 
24817
24850
  const indexEntries = Object.entries(table.indexes);
@@ -24837,7 +24870,7 @@
24837
24870
  cellElement.innerText = value;
24838
24871
  rowElement.appendChild(cellElement);
24839
24872
  };
24840
- createTable(indexesElement, columns, rows, 'tables-table', cellRenderer);
24873
+ indexesElement.appendChild(new ResizeTable(columns, rows, cellRenderer));
24841
24874
  }
24842
24875
  });
24843
24876
  window.structureLoaded = true;
@@ -25291,20 +25324,18 @@
25291
25324
 
25292
25325
  let tableElement = document.getElementById('result-table');
25293
25326
  if (tableElement) {
25294
- const resultBody = getTableBody(tableElement);
25327
+ const resultBody = tableElement.getTableBody();
25295
25328
  if (resultBody.dataset.page === fetch.page) {
25296
25329
  // Results already displayed.
25297
25330
  return
25298
25331
  }
25299
- setTableBody(rows, tableElement, resultCellRenderer);
25332
+ tableElement.updateTableBody(rows, resultCellRenderer);
25300
25333
  } else {
25301
25334
  clearResultBox();
25302
- tableElement = createTable(
25303
- document.getElementById('result-box'),
25304
- fetch.result.columns,
25305
- rows,
25306
- 'result-table',
25307
- resultCellRenderer);
25335
+ const resultBoxElement = document.getElementById('result-box');
25336
+ tableElement = new ResizeTable(fetch.result.columns, rows, resultCellRenderer);
25337
+ tableElement.id = 'result-table';
25338
+ resultBoxElement.appendChild(tableElement);
25308
25339
  }
25309
25340
  tableElement.setAttribute('data-page', fetch.page);
25310
25341
  }
@@ -25462,7 +25493,7 @@
25462
25493
  }
25463
25494
 
25464
25495
  if (result.total_rows > result.rows.length) {
25465
- message += ` (truncated to ${result.rows.length})`;
25496
+ message += ` (truncated to ${result.rows.length.toLocaleString()})`;
25466
25497
  }
25467
25498
  setStatus(message);
25468
25499
 
@@ -25474,6 +25505,16 @@
25474
25505
  document.getElementById('next-button').disabled = sqlFetch.page + 1 === sqlFetch.pageCount;
25475
25506
  document.getElementById('prev-button').disabled = sqlFetch.page === 0;
25476
25507
  }
25508
+
25509
+ if (sqlFetch.pageCount > 2) {
25510
+ document.getElementById('first-button').style.display = 'flex';
25511
+ document.getElementById('last-button').style.display = 'flex';
25512
+ document.getElementById('first-button').disabled = sqlFetch.page === 0;
25513
+ document.getElementById('last-button').disabled = sqlFetch.page === sqlFetch.pageCount - 1;
25514
+ } else {
25515
+ document.getElementById('last-button').style.display = 'none';
25516
+ document.getElementById('first-button').style.display = 'none';
25517
+ }
25477
25518
  }
25478
25519
 
25479
25520
  window.addEventListener('popstate', function (event) {
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.56
4
+ version: 0.1.58
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-12-09 00:00:00.000000000 Z
11
+ date: 2022-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: airbrake