sqlui 0.1.20 → 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/mysql_types.rb +1 -1
- data/app/server.rb +19 -17
- data/app/views/databases.erb +70 -38
- data/client/resources/sqlui.css +46 -21
- data/client/resources/sqlui.html +2 -2
- data/client/resources/sqlui.js +2 -1
- 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: 1781b502f4bf82b9a87461d495cb6776f9290bfb5a2809a7ddb12e992ce7cc5c
|
4
|
+
data.tar.gz: a992696d1bbd1f809290035fa23c7cfec262f827073665e9013254420794d6d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6bfc097c3e9f427aec918c9b3eabeef74a69a3109fff6588c2a87201c9f43a7a0839463ec1cbe400b5d880ee1c3f069e6ecea6978acb02fd152633cc841f448
|
7
|
+
data.tar.gz: 9ec1cfb0f64cc425331723856e89aab3d2fac02f107a381a7c7ab6b2f1c4f0ee40adbe87b458c14fb537fe72ecb5eff044f02812e82fceb9c1263cff369a6ee3
|
data/.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.21
|
data/app/mysql_types.rb
CHANGED
data/app/server.rb
CHANGED
@@ -56,12 +56,11 @@ class Server < Sinatra::Base
|
|
56
56
|
end
|
57
57
|
|
58
58
|
get "#{database.url_path}/metadata" do
|
59
|
-
|
60
|
-
metadata = database_config.with_client do |client|
|
59
|
+
metadata = database.with_client do |client|
|
61
60
|
{
|
62
61
|
server: config.name,
|
63
|
-
schemas: DatabaseMetadata.lookup(client,
|
64
|
-
saved: Dir.glob("#{
|
62
|
+
schemas: DatabaseMetadata.lookup(client, database),
|
63
|
+
saved: Dir.glob("#{database.saved_path}/*.sql").map do |path|
|
65
64
|
comment_lines = File.readlines(path).take_while do |l|
|
66
65
|
l.start_with?('--')
|
67
66
|
end
|
@@ -80,11 +79,12 @@ class Server < Sinatra::Base
|
|
80
79
|
|
81
80
|
get "#{database.url_path}/query_file" do
|
82
81
|
break client_error('missing file param') unless params[:file]
|
83
|
-
break client_error('no such file') unless File.exist?(params[:file])
|
84
82
|
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
file = File.join(database.saved_path, params[:file])
|
84
|
+
break client_error('no such file') unless File.exist?(file)
|
85
|
+
|
86
|
+
sql = File.read(file)
|
87
|
+
result = database.with_client do |client|
|
88
88
|
execute_query(client, sql).tap { |r| r[:file] = params[:file] }
|
89
89
|
end
|
90
90
|
|
@@ -110,8 +110,7 @@ class Server < Sinatra::Base
|
|
110
110
|
break client_error("can't find query at selection") unless sql
|
111
111
|
end
|
112
112
|
|
113
|
-
|
114
|
-
result = database_config.with_client do |client|
|
113
|
+
result = database.with_client do |client|
|
115
114
|
execute_query(client, sql)
|
116
115
|
end
|
117
116
|
|
@@ -126,8 +125,10 @@ class Server < Sinatra::Base
|
|
126
125
|
error do |e|
|
127
126
|
status 500
|
128
127
|
headers 'Content-Type': 'application/json'
|
128
|
+
message = e.message.lines.first&.strip || 'unexpected error'
|
129
|
+
message = "#{message[0..80]}…" if message.length > 80
|
129
130
|
result = {
|
130
|
-
error:
|
131
|
+
error: message,
|
131
132
|
stacktrace: e.backtrace.map { |b| b }.join("\n")
|
132
133
|
}
|
133
134
|
body result.to_json
|
@@ -145,12 +146,13 @@ class Server < Sinatra::Base
|
|
145
146
|
end
|
146
147
|
|
147
148
|
def execute_query(client, sql)
|
148
|
-
if sql.include?(';')
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
149
|
+
queries = if sql.include?(';')
|
150
|
+
sql.split(/(?<=;)/).map(&:strip).reject(&:empty?)
|
151
|
+
else
|
152
|
+
[sql]
|
153
|
+
end
|
154
|
+
results = queries.map { |current| client.query(current) }
|
155
|
+
result = results[-1]
|
154
156
|
# NOTE: the call to result.field_types must go before any other interaction with the result. Otherwise you will
|
155
157
|
# get a seg fault. Seems to be a bug in Mysql2.
|
156
158
|
if result
|
data/app/views/databases.erb
CHANGED
@@ -1,66 +1,98 @@
|
|
1
1
|
<html>
|
2
|
-
|
3
|
-
|
2
|
+
<head>
|
3
|
+
<title>Databases</title>
|
4
4
|
|
5
|
-
|
5
|
+
<style>
|
6
6
|
body {
|
7
|
-
|
8
|
-
|
7
|
+
font-family: Helvetica;
|
8
|
+
margin: 0px;
|
9
9
|
}
|
10
10
|
|
11
11
|
h1 {
|
12
|
-
|
13
|
-
|
12
|
+
font-size: 22px;
|
13
|
+
}
|
14
|
+
|
15
|
+
h2 {
|
16
|
+
font-size: 20px;
|
17
|
+
}
|
18
|
+
|
19
|
+
p {
|
20
|
+
font-size: 18px;
|
21
|
+
}
|
22
|
+
|
23
|
+
.header-box {
|
24
|
+
display: flex;
|
25
|
+
flex-direction: row;
|
26
|
+
border-bottom: 1px solid #ddd;
|
27
|
+
height: 36px;
|
28
|
+
font-family: Helvetica;
|
29
|
+
}
|
30
|
+
|
31
|
+
.header, .server-name {
|
32
|
+
display: flex;
|
33
|
+
align-items: center;
|
34
|
+
justify-content: start;
|
35
|
+
color: #333;
|
36
|
+
}
|
37
|
+
|
38
|
+
.server-name {
|
39
|
+
flex: 1;
|
40
|
+
padding-left: 15px;
|
41
|
+
font-weight: normal;
|
42
|
+
}
|
14
43
|
|
44
|
+
.header {
|
45
|
+
font-weight: bold;
|
46
|
+
padding-left: 5px;
|
15
47
|
}
|
16
48
|
|
17
49
|
.database a {
|
18
|
-
|
19
|
-
|
20
|
-
|
50
|
+
margin-right: 10px;
|
51
|
+
color: darkblue;
|
52
|
+
font-size: 16px
|
21
53
|
}
|
22
54
|
|
23
55
|
.database h2 {
|
24
|
-
|
25
|
-
font-size: 20px;
|
26
|
-
font-weight: bold;
|
56
|
+
margin: 0px;
|
27
57
|
}
|
28
58
|
|
29
59
|
.database p {
|
30
|
-
|
31
|
-
|
32
|
-
font-size: 16px;
|
60
|
+
margin: 0px;
|
61
|
+
margin-top: 10px;
|
33
62
|
}
|
34
63
|
|
35
64
|
.database {
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
65
|
+
margin: 0px;
|
66
|
+
padding: 10px;
|
67
|
+
cursor: pointer;
|
68
|
+
border-bottom: 1px solid #eeeeee;
|
40
69
|
}
|
41
70
|
|
42
71
|
.database:last-child {
|
43
|
-
|
72
|
+
border-bottom: none;
|
44
73
|
}
|
45
74
|
|
46
75
|
.database:hover {
|
47
|
-
|
76
|
+
background: #eee;
|
48
77
|
}
|
49
|
-
|
50
|
-
|
78
|
+
</style>
|
79
|
+
</head>
|
51
80
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
81
|
+
<body>
|
82
|
+
<div class="header-box">
|
83
|
+
<h1 class="header">SQLUI</h1>
|
84
|
+
<h1 class="server-name"><%= config.name %> Databases</h1>
|
85
|
+
</div>
|
86
|
+
<% config.database_configs.each do |database_config| %>
|
87
|
+
<div class="database" onclick="window.location='<%= "#{database_config.url_path}/app" %>'">
|
88
|
+
<h2 class='name'><%= database_config.display_name %></h2>
|
89
|
+
<a class='query-link' href="<%= database_config.url_path %>/app">query</a>
|
90
|
+
<a class='saved-link' href="<%= database_config.url_path %>/app?tab=saved">saved</a>
|
91
|
+
<a class='structure-link' href="<%= database_config.url_path %>/app?tab=structure">structure</a>
|
92
|
+
<p class='description'>
|
93
|
+
<%= database_config.description %>
|
94
|
+
</p>
|
95
|
+
</div>
|
96
|
+
<% end %>
|
97
|
+
</body>
|
66
98
|
</html>
|
data/client/resources/sqlui.css
CHANGED
@@ -2,6 +2,18 @@ body {
|
|
2
2
|
margin: 0;
|
3
3
|
}
|
4
4
|
|
5
|
+
h1 {
|
6
|
+
font-size: 22px;
|
7
|
+
}
|
8
|
+
|
9
|
+
h2 {
|
10
|
+
font-size: 20px;
|
11
|
+
}
|
12
|
+
|
13
|
+
p {
|
14
|
+
font-size: 18px;
|
15
|
+
}
|
16
|
+
|
5
17
|
.loading-box {
|
6
18
|
font-family: monospace;
|
7
19
|
display: flex;
|
@@ -13,6 +25,7 @@ body {
|
|
13
25
|
align-items: start;
|
14
26
|
justify-content: start;
|
15
27
|
padding: 10px;
|
28
|
+
color: #333;
|
16
29
|
}
|
17
30
|
|
18
31
|
.main-box {
|
@@ -36,9 +49,15 @@ body {
|
|
36
49
|
padding-left: 5px;
|
37
50
|
}
|
38
51
|
|
52
|
+
.header a {
|
53
|
+
text-decoration: none;
|
54
|
+
color: #333
|
55
|
+
}
|
56
|
+
|
39
57
|
.server-name {
|
40
58
|
flex: 1;
|
41
59
|
padding-left: 15px;
|
60
|
+
font-weight: normal;
|
42
61
|
}
|
43
62
|
|
44
63
|
.tabs-box {
|
@@ -46,7 +65,7 @@ body {
|
|
46
65
|
flex-direction: row;
|
47
66
|
border-bottom: 1px solid #ddd;
|
48
67
|
height: 36px;
|
49
|
-
font-family: Helvetica;
|
68
|
+
font-family: Helvetica, sans-serif;
|
50
69
|
}
|
51
70
|
|
52
71
|
.tab-button, .selected-tab-button {
|
@@ -55,10 +74,11 @@ body {
|
|
55
74
|
cursor: pointer;
|
56
75
|
width: 150px;
|
57
76
|
padding: 2px;
|
58
|
-
margin:
|
77
|
+
margin: 0;
|
59
78
|
display: flex;
|
60
79
|
justify-content: center;
|
61
80
|
background-color: #fff;
|
81
|
+
font-size: 18px;
|
62
82
|
}
|
63
83
|
|
64
84
|
.tab-button {
|
@@ -100,6 +120,8 @@ body {
|
|
100
120
|
border: 1px solid #888;
|
101
121
|
background: none;
|
102
122
|
padding: 5px;
|
123
|
+
font-size: 18px;
|
124
|
+
color: #333;
|
103
125
|
}
|
104
126
|
|
105
127
|
.status {
|
@@ -107,9 +129,11 @@ body {
|
|
107
129
|
justify-content: center;
|
108
130
|
align-content: center;
|
109
131
|
flex-direction: column;
|
110
|
-
font-family: Helvetica;
|
132
|
+
font-family: Helvetica, sans-serif;
|
111
133
|
white-space: nowrap;
|
112
134
|
overflow: hidden;
|
135
|
+
font-size: 18px;
|
136
|
+
color: #333;
|
113
137
|
}
|
114
138
|
|
115
139
|
.result-box, .saved-box, .graph-box, .structure-box {
|
@@ -130,9 +154,10 @@ body {
|
|
130
154
|
table {
|
131
155
|
font-family: monospace;
|
132
156
|
flex: 1;
|
133
|
-
border-spacing:
|
157
|
+
border-spacing: 0;
|
134
158
|
display: flex;
|
135
159
|
width: 100%;
|
160
|
+
color: #333;
|
136
161
|
}
|
137
162
|
|
138
163
|
table td:last-child, table th:last-child {
|
@@ -165,11 +190,11 @@ table {
|
|
165
190
|
}
|
166
191
|
|
167
192
|
thead {
|
168
|
-
padding:
|
193
|
+
padding: 0;
|
169
194
|
background-color: #fff;
|
170
195
|
position: -webkit-sticky;
|
171
196
|
position: sticky;
|
172
|
-
top:
|
197
|
+
top: 0;
|
173
198
|
z-index: 100;
|
174
199
|
table-layout: fixed;
|
175
200
|
}
|
@@ -181,7 +206,7 @@ thead {
|
|
181
206
|
.status-box {
|
182
207
|
padding: 5px;
|
183
208
|
display: flex;
|
184
|
-
flex-direction:
|
209
|
+
flex-direction: row;
|
185
210
|
justify-content: space-between;
|
186
211
|
border-top: 1px solid #ddd;
|
187
212
|
height: 30px;
|
@@ -196,31 +221,31 @@ thead {
|
|
196
221
|
}
|
197
222
|
|
198
223
|
.saved-box {
|
199
|
-
font-family: Helvetica;
|
224
|
+
font-family: Helvetica, sans-serif;
|
200
225
|
}
|
201
226
|
|
202
|
-
.saved-box
|
203
|
-
margin:
|
204
|
-
padding-left: 10px;
|
205
|
-
padding-right: 10px;
|
206
|
-
padding-top: 10px;
|
207
|
-
padding-bottom: 10px;
|
227
|
+
.saved-box h2 {
|
228
|
+
margin: 0;
|
208
229
|
font-weight: bold;
|
209
230
|
}
|
210
231
|
|
211
|
-
.saved-
|
232
|
+
.saved-list-item:last-child {
|
212
233
|
border-top: none !important;
|
213
234
|
}
|
214
235
|
|
215
236
|
.saved-box p {
|
216
|
-
margin:
|
217
|
-
padding-left: 20px;
|
218
|
-
padding-bottom: 20px;
|
237
|
+
margin: 0;
|
219
238
|
}
|
220
239
|
|
221
|
-
.saved-
|
240
|
+
.saved-list-item {
|
222
241
|
cursor: pointer;
|
223
|
-
border-
|
242
|
+
border-bottom: 1px solid #eeeeee;
|
243
|
+
margin: 0;
|
244
|
+
padding: 10px;
|
245
|
+
}
|
246
|
+
|
247
|
+
.saved-list-item h2 {
|
248
|
+
margin: 0 0 5px;
|
224
249
|
}
|
225
250
|
|
226
251
|
.saved-box div:hover {
|
@@ -239,7 +264,6 @@ thead {
|
|
239
264
|
|
240
265
|
.table-info {
|
241
266
|
display: grid;
|
242
|
-
grid-template-columns: 1;
|
243
267
|
grid-template-rows: 0.5fr 0.5fr;
|
244
268
|
justify-items: stretch;
|
245
269
|
flex: 1;
|
@@ -260,4 +284,5 @@ thead {
|
|
260
284
|
|
261
285
|
select {
|
262
286
|
outline: none;
|
287
|
+
color: #333;
|
263
288
|
}
|
data/client/resources/sqlui.html
CHANGED
@@ -13,8 +13,8 @@
|
|
13
13
|
|
14
14
|
<div id="main-box" class="main-box" style="display:none">
|
15
15
|
<div class="tabs-box">
|
16
|
-
<
|
17
|
-
<
|
16
|
+
<h1 class="header"><a href="/sqlui">SQLUI</a></h1>
|
17
|
+
<h1 id="server-name" class="server-name"></h1>
|
18
18
|
<input id="query-tab-button" class="tab-button" type="button" value="Query" onclick="sqlui.selectTab('query')"></input>
|
19
19
|
<input id="graph-tab-button" class="tab-button" type="button" value="Graph" onclick="sqlui.selectTab('graph')"></input>
|
20
20
|
<input id="saved-tab-button" class="tab-button" type="button" value="Saved" onclick="sqlui.selectTab('saved')"></input>
|
data/client/resources/sqlui.js
CHANGED
@@ -24156,6 +24156,7 @@ var sqlui = (function (exports) {
|
|
24156
24156
|
}
|
24157
24157
|
saved.forEach(file => {
|
24158
24158
|
const divElement = document.createElement('div');
|
24159
|
+
divElement.classList.add('saved-list-item');
|
24159
24160
|
divElement.addEventListener('click', function (event) {
|
24160
24161
|
clearResult();
|
24161
24162
|
const url = new URL(window.location);
|
@@ -24165,7 +24166,7 @@ var sqlui = (function (exports) {
|
|
24165
24166
|
window.history.pushState({}, '', url);
|
24166
24167
|
route();
|
24167
24168
|
});
|
24168
|
-
const nameElement = document.createElement('
|
24169
|
+
const nameElement = document.createElement('h2');
|
24169
24170
|
nameElement.innerText = file.filename;
|
24170
24171
|
divElement.appendChild(nameElement);
|
24171
24172
|
|
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
|