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 +4 -4
- data/.release-version +1 -1
- data/app/server.rb +37 -25
- data/app/sql_parser.rb +4 -0
- data/app/sqlui.rb +2 -2
- data/app/views/sqlui.erb +2 -0
- data/client/resources/sqlui.css +6 -10
- data/client/resources/sqlui.js +179 -138
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0a7dab933454e7e153894eb7e0317680dd1f4aa88953480b31d94a825f95f10
|
|
4
|
+
data.tar.gz: 6cf9998337f955912eb5a050dfd024bee292afef191a2ee639cda5552e86490c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f0da91f85d1880eec8ef7d99e5858c49f61334dbabf7d8286b226f34ff9984d5faf30eb4c1be59ea810c4f45e7a148782eadd5d0fb4c488c96403d96d6257b84
|
|
7
|
+
data.tar.gz: b1da77e8601b4a7c48bedadcb6e513ef7729893eaad9e30232d1dadb1d600d5ad6f127c28726eb009bbc6abc274369b1fe99d611dc69dae3d353db00c3ea4f59
|
data/.release-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
265
|
-
|
|
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
|
|
269
|
+
SqlParser.split(full_sql)
|
|
268
270
|
end
|
|
269
271
|
end
|
|
270
272
|
|
|
271
|
-
def execute_query(client, variables,
|
|
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
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 =
|
|
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>
|
data/client/resources/sqlui.css
CHANGED
|
@@ -228,7 +228,7 @@ p {
|
|
|
228
228
|
background: none !important;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
|
|
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;
|
data/client/resources/sqlui.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
24314
|
-
|
|
24315
|
-
|
|
24316
|
-
|
|
24317
|
-
|
|
24318
|
-
}
|
|
24319
|
-
|
|
24320
|
-
|
|
24321
|
-
|
|
24322
|
-
|
|
24323
|
-
|
|
24324
|
-
|
|
24325
|
-
|
|
24326
|
-
|
|
24327
|
-
|
|
24328
|
-
|
|
24329
|
-
|
|
24330
|
-
|
|
24331
|
-
|
|
24332
|
-
|
|
24333
|
-
|
|
24334
|
-
|
|
24335
|
-
|
|
24336
|
-
|
|
24337
|
-
|
|
24338
|
-
}
|
|
24339
|
-
|
|
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
|
-
|
|
24360
|
+
lastColWidth = (drag.scrollOffset + drag.containerWidth) - (drag.tableElement.columnsWidth);
|
|
24356
24361
|
} else {
|
|
24357
|
-
|
|
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
|
-
|
|
24362
|
-
|
|
24363
|
-
|
|
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
|
-
|
|
24368
|
-
|
|
24369
|
-
if (id) tableElement.id = id;
|
|
24370
|
-
tableElement.style.tableLayout = 'auto';
|
|
24372
|
+
this.columns = columns;
|
|
24373
|
+
this.cellRenderer = cellRenderer;
|
|
24371
24374
|
|
|
24372
|
-
|
|
24373
|
-
|
|
24375
|
+
this.style.tableLayout = 'auto';
|
|
24376
|
+
this.style.width = '100%';
|
|
24374
24377
|
|
|
24375
|
-
|
|
24376
|
-
|
|
24378
|
+
const colgroupElement = document.createElement('colgroup');
|
|
24379
|
+
this.appendChild(colgroupElement);
|
|
24377
24380
|
|
|
24378
|
-
|
|
24379
|
-
|
|
24381
|
+
const theadElement = document.createElement('thead');
|
|
24382
|
+
this.appendChild(theadElement);
|
|
24380
24383
|
|
|
24381
|
-
|
|
24382
|
-
|
|
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
|
-
|
|
24388
|
-
|
|
24389
|
-
|
|
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
|
-
|
|
24392
|
-
|
|
24393
|
-
|
|
24393
|
+
const contentWrapperElement = document.createElement('div');
|
|
24394
|
+
contentWrapperElement.classList.add('col-content-wrapper');
|
|
24395
|
+
headerElement.appendChild(contentWrapperElement);
|
|
24394
24396
|
|
|
24395
|
-
|
|
24396
|
-
|
|
24397
|
-
|
|
24398
|
-
colElements.push(colElement);
|
|
24397
|
+
const nameElement = document.createElement('div');
|
|
24398
|
+
nameElement.classList.add('col-name');
|
|
24399
|
+
contentWrapperElement.appendChild(nameElement);
|
|
24399
24400
|
|
|
24400
|
-
|
|
24401
|
-
|
|
24402
|
-
|
|
24403
|
-
|
|
24401
|
+
const colElement = document.createElement('col');
|
|
24402
|
+
colElement.dataset.colId = `col-${index}`;
|
|
24403
|
+
colgroupElement.appendChild(colElement);
|
|
24404
|
+
colElements.push(colElement);
|
|
24404
24405
|
|
|
24405
|
-
|
|
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
|
-
|
|
24409
|
-
|
|
24410
|
-
lastColElement.style.width = '100%';
|
|
24411
|
-
colElements.push(lastColElement);
|
|
24411
|
+
nameElement.innerText = column;
|
|
24412
|
+
});
|
|
24412
24413
|
|
|
24413
|
-
|
|
24414
|
-
|
|
24415
|
-
|
|
24416
|
-
|
|
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
|
-
|
|
24430
|
-
|
|
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
|
-
|
|
24433
|
-
|
|
24434
|
-
|
|
24435
|
-
|
|
24436
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24449
|
-
|
|
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
|
-
|
|
24453
|
-
|
|
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
|
-
|
|
24456
|
-
tbodyElement?.parentElement?.removeChild(tbodyElement);
|
|
24465
|
+
colgroupElement.appendChild(lastColElement);
|
|
24457
24466
|
|
|
24458
|
-
|
|
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
|
-
|
|
24468
|
-
|
|
24469
|
-
|
|
24470
|
-
|
|
24471
|
-
|
|
24472
|
-
|
|
24473
|
-
|
|
24474
|
-
|
|
24475
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
25327
|
+
const resultBody = tableElement.getTableBody();
|
|
25295
25328
|
if (resultBody.dataset.page === fetch.page) {
|
|
25296
25329
|
// Results already displayed.
|
|
25297
25330
|
return
|
|
25298
25331
|
}
|
|
25299
|
-
|
|
25332
|
+
tableElement.updateTableBody(rows, resultCellRenderer);
|
|
25300
25333
|
} else {
|
|
25301
25334
|
clearResultBox();
|
|
25302
|
-
|
|
25303
|
-
|
|
25304
|
-
|
|
25305
|
-
|
|
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.
|
|
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-
|
|
11
|
+
date: 2022-12-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: airbrake
|