blazer 1.6.1 → 1.6.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of blazer might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +17 -1
- data/app/assets/javascripts/blazer/application.js +29 -3
- data/app/assets/stylesheets/blazer/application.css +32 -0
- data/app/controllers/blazer/base_controller.rb +14 -0
- data/app/controllers/blazer/dashboards_controller.rb +3 -6
- data/app/controllers/blazer/queries_controller.rb +22 -9
- data/app/models/blazer/query.rb +1 -1
- data/app/views/blazer/dashboards/_form.html.erb +0 -16
- data/app/views/blazer/dashboards/show.html.erb +1 -15
- data/app/views/blazer/queries/_form.html.erb +34 -15
- data/app/views/blazer/queries/home.html.erb +18 -14
- data/app/views/blazer/queries/schema.html.erb +18 -0
- data/app/views/blazer/queries/show.html.erb +1 -15
- data/config/routes.rb +1 -0
- data/lib/blazer/adapters/base_adapter.rb +4 -0
- data/lib/blazer/adapters/mongodb_adapter.rb +1 -1
- data/lib/blazer/adapters/sql_adapter.rb +5 -0
- data/lib/blazer/version.rb +1 -1
- data/lib/generators/blazer/templates/config.yml +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72563e8886e9e04823f21ad5e7ca11f5cc112b81
|
4
|
+
data.tar.gz: 51c6ed0f30b9eafc05a77aa3dff44ae44f2092e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50a816c915b87433037a0eff3e7477708a6c99e8197638a1a5f1a04865d59a70ce45feab5dfdefe864012e15835d556145fe0ae05ce3f4c903c23b068aafb04b
|
7
|
+
data.tar.gz: 0fc76958a41ebd094be658cd429ecb2c3984e67d152c067540fb921c3b93e6790c3c56b8e7eda1d2753c18a05d9b37658383ab9b2daa6c3cc81597125b79e16a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -191,6 +191,14 @@ smart_variables:
|
|
191
191
|
|
192
192
|
The first column is the value of the variable, and the second column is the label.
|
193
193
|
|
194
|
+
You can also use an array or hash for static data and enums.
|
195
|
+
|
196
|
+
```yml
|
197
|
+
smart_variables:
|
198
|
+
period: ["day", "week", "month"]
|
199
|
+
status: {0: "Active", 1: "Archived"}
|
200
|
+
```
|
201
|
+
|
194
202
|
### Linked Columns
|
195
203
|
|
196
204
|
[Example](https://blazerme.herokuapp.com/queries/3-linked-column) - title column
|
@@ -280,7 +288,7 @@ SELECT gender, zip_code, COUNT(*) FROM users GROUP BY 1, 2
|
|
280
288
|
|
281
289
|
### Maps
|
282
290
|
|
283
|
-
Columns named `latitude` and `longitude` or `lat` and `lon` - [Example](https://blazerme.herokuapp.com/queries/15-map)
|
291
|
+
Columns named `latitude` and `longitude` or `lat` and `lon` or `lat` and `lng` - [Example](https://blazerme.herokuapp.com/queries/15-map)
|
284
292
|
|
285
293
|
```sql
|
286
294
|
SELECT name, latitude, longitude FROM cities
|
@@ -420,6 +428,14 @@ data_sources:
|
|
420
428
|
url: presto://user@hostname:8080/catalog
|
421
429
|
```
|
422
430
|
|
431
|
+
## Permissions [master]
|
432
|
+
|
433
|
+
Blazer supports a simple permissions model.
|
434
|
+
|
435
|
+
1. Queries without a name are unlisted
|
436
|
+
2. Queries whose name starts with `#` are only listed to the creator
|
437
|
+
3. Queries whose name starts with `*` can only be edited by the creator
|
438
|
+
|
423
439
|
## Learn SQL
|
424
440
|
|
425
441
|
Have team members who want to learn SQL? Here are a few great, free resources.
|
@@ -25,8 +25,16 @@ $( function () {
|
|
25
25
|
});
|
26
26
|
});
|
27
27
|
|
28
|
-
function
|
29
|
-
|
28
|
+
function cancelQuery(runningQuery) {
|
29
|
+
runningQuery.canceled = true;
|
30
|
+
var xhr = runningQuery.xhr;
|
31
|
+
if (xhr) {
|
32
|
+
xhr.abort();
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
function runQuery(data, success, error, runningQuery) {
|
37
|
+
var xhr = $.ajax({
|
30
38
|
url: window.runQueriesPath,
|
31
39
|
method: "POST",
|
32
40
|
data: data,
|
@@ -36,7 +44,9 @@ function runQuery(data, success, error) {
|
|
36
44
|
var response = $.parseJSON(d);
|
37
45
|
data.blazer = response;
|
38
46
|
setTimeout( function () {
|
39
|
-
|
47
|
+
if (!(runningQuery && runningQuery.canceled)) {
|
48
|
+
runQuery(data, success, error, runningQuery);
|
49
|
+
}
|
40
50
|
}, 1000);
|
41
51
|
} else {
|
42
52
|
success(d);
|
@@ -45,6 +55,22 @@ function runQuery(data, success, error) {
|
|
45
55
|
var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
|
46
56
|
error(message);
|
47
57
|
});
|
58
|
+
if (runningQuery) {
|
59
|
+
runningQuery.xhr = xhr;
|
60
|
+
}
|
61
|
+
return xhr;
|
62
|
+
}
|
63
|
+
|
64
|
+
function submitIfCompleted($form) {
|
65
|
+
var completed = true;
|
66
|
+
$form.find("input[name], select").each( function () {
|
67
|
+
if ($(this).val() == "") {
|
68
|
+
completed = false;
|
69
|
+
}
|
70
|
+
});
|
71
|
+
if (completed) {
|
72
|
+
$form.submit();
|
73
|
+
}
|
48
74
|
}
|
49
75
|
|
50
76
|
// Prevent backspace from navigating backwards.
|
@@ -55,6 +55,10 @@ input.search:focus {
|
|
55
55
|
text-align: left;
|
56
56
|
}
|
57
57
|
|
58
|
+
#statement-box .selectize-control {
|
59
|
+
margin-right: 0;
|
60
|
+
}
|
61
|
+
|
58
62
|
#editor-container {
|
59
63
|
background-color: #141414;
|
60
64
|
padding-top: 10px;
|
@@ -133,3 +137,31 @@ input.search:focus {
|
|
133
137
|
.check-state.disabled {
|
134
138
|
color: #000;
|
135
139
|
}
|
140
|
+
|
141
|
+
.topbar {
|
142
|
+
position: fixed;
|
143
|
+
top: 0;
|
144
|
+
left: 0;
|
145
|
+
right: 0;
|
146
|
+
background-color: whitesmoke;
|
147
|
+
height: 60px;
|
148
|
+
z-index: 1001;
|
149
|
+
}
|
150
|
+
|
151
|
+
.glyphicon-remove {
|
152
|
+
cursor: pointer;
|
153
|
+
color: #d9534f;
|
154
|
+
display: none;
|
155
|
+
}
|
156
|
+
|
157
|
+
.list-group li:hover .glyphicon-remove {
|
158
|
+
display: inline;
|
159
|
+
}
|
160
|
+
|
161
|
+
.list-group {
|
162
|
+
cursor: move;
|
163
|
+
}
|
164
|
+
|
165
|
+
#header a.active {
|
166
|
+
color: #999;
|
167
|
+
}
|
@@ -50,6 +50,20 @@ module Blazer
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
def parse_smart_variables(var, data_source)
|
54
|
+
query = data_source.smart_variables[var]
|
55
|
+
if query.is_a? Hash
|
56
|
+
smart_var = query.map { |k,v| [v, k] }
|
57
|
+
elsif query.is_a? Array
|
58
|
+
smart_var = query.map { |v| [v, v] }
|
59
|
+
elsif query
|
60
|
+
result = data_source.run_statement(query)
|
61
|
+
smart_var = result.rows.map { |v| v.reverse }
|
62
|
+
error = result.error if result.error
|
63
|
+
end
|
64
|
+
return smart_var, error
|
65
|
+
end
|
66
|
+
|
53
67
|
def extract_vars(statement)
|
54
68
|
# strip commented out lines
|
55
69
|
# and regex {1} or {1,2}
|
@@ -35,12 +35,9 @@ module Blazer
|
|
35
35
|
@data_sources = @queries.map { |q| Blazer.data_sources[q.data_source] }.uniq
|
36
36
|
@bind_vars.each do |var|
|
37
37
|
@data_sources.each do |data_source|
|
38
|
-
|
39
|
-
if
|
40
|
-
|
41
|
-
((@smart_vars[var] ||= []).concat(result.rows.map { |v| v.reverse })).uniq!
|
42
|
-
@sql_errors << result.error if result.error
|
43
|
-
end
|
38
|
+
smart_var, error = parse_smart_variables(var, data_source)
|
39
|
+
((@smart_vars[var] ||= []).concat(smart_var)).uniq! if smart_var
|
40
|
+
@sql_errors << error if error
|
44
41
|
end
|
45
42
|
end
|
46
43
|
end
|
@@ -7,6 +7,9 @@ module Blazer
|
|
7
7
|
|
8
8
|
@dashboards = Blazer::Dashboard.order(:name)
|
9
9
|
@dashboards = @dashboards.includes(:creator) if Blazer.user_class
|
10
|
+
if params[:filter] == "mine"
|
11
|
+
@dashboards = [] # TODO show my dashboards
|
12
|
+
end
|
10
13
|
@dashboards =
|
11
14
|
@dashboards.map do |d|
|
12
15
|
{
|
@@ -52,12 +55,9 @@ module Blazer
|
|
52
55
|
@sql_errors = []
|
53
56
|
data_source = Blazer.data_sources[@query.data_source]
|
54
57
|
@bind_vars.each do |var|
|
55
|
-
|
56
|
-
if
|
57
|
-
|
58
|
-
@smart_vars[var] = result.rows.map { |v| v.reverse }
|
59
|
-
@sql_errors << result.error if result.error
|
60
|
-
end
|
58
|
+
smart_var, error = parse_smart_variables(var, data_source)
|
59
|
+
@smart_vars[var] = smart_var if smart_var
|
60
|
+
@sql_errors << error if error
|
61
61
|
end
|
62
62
|
|
63
63
|
Blazer.transform_statement.call(data_source, @statement) if Blazer.transform_statement
|
@@ -170,6 +170,10 @@ module Blazer
|
|
170
170
|
render partial: "tables", layout: false
|
171
171
|
end
|
172
172
|
|
173
|
+
def schema
|
174
|
+
@schema = Blazer.data_sources[params[:data_source]].schema
|
175
|
+
end
|
176
|
+
|
173
177
|
private
|
174
178
|
|
175
179
|
def continue_run
|
@@ -204,7 +208,7 @@ module Blazer
|
|
204
208
|
@linked_columns = @data_source.linked_columns
|
205
209
|
|
206
210
|
@markers = []
|
207
|
-
[["latitude", "longitude"], ["lat", "lon"]].each do |keys|
|
211
|
+
[["latitude", "longitude"], ["lat", "lon"], ["lat", "lng"]].each do |keys|
|
208
212
|
lat_index = @columns.index(keys.first)
|
209
213
|
lon_index = @columns.index(keys.last)
|
210
214
|
if lat_index && lon_index
|
@@ -233,7 +237,7 @@ module Blazer
|
|
233
237
|
|
234
238
|
def set_queries(limit = nil)
|
235
239
|
@my_queries =
|
236
|
-
if limit && blazer_user
|
240
|
+
if limit && blazer_user && !params[:filter]
|
237
241
|
favorite_query_ids = Blazer::Audit.where(user_id: blazer_user.id).where("created_at > ?", 30.days.ago).where("query_id IS NOT NULL").group(:query_id).order("count_all desc").count.keys
|
238
242
|
queries = Blazer::Query.named.where(id: favorite_query_ids)
|
239
243
|
queries = queries.includes(:creator) if Blazer.user_class
|
@@ -244,12 +248,21 @@ module Blazer
|
|
244
248
|
end
|
245
249
|
|
246
250
|
@queries = Blazer::Query.named.order(:name)
|
251
|
+
if params[:filter] == "mine"
|
252
|
+
@queries = @queries.where(creator_id: blazer_user.try(:id)).reorder(updated_at: :desc)
|
253
|
+
limit = nil
|
254
|
+
end
|
247
255
|
@queries = @queries.where("id NOT IN (?)", @my_queries.map(&:id)) if @my_queries.any?
|
248
256
|
@queries = @queries.includes(:creator) if Blazer.user_class
|
249
257
|
@queries = @queries.limit(limit) if limit
|
258
|
+
@queries = @queries.to_a
|
259
|
+
|
260
|
+
@more = limit && @queries.size >= limit
|
261
|
+
|
262
|
+
@queries = (@my_queries + @queries).select { |q| !q.name.to_s.start_with?("#") || q.try(:creator).try(:id) == blazer_user.try(:id) }
|
250
263
|
|
251
264
|
@queries =
|
252
|
-
|
265
|
+
@queries.map do |q|
|
253
266
|
{
|
254
267
|
id: q.id,
|
255
268
|
name: view_context.link_to(q.name, q),
|
data/app/models/blazer/query.rb
CHANGED
@@ -2,22 +2,6 @@
|
|
2
2
|
<div class="alert alert-danger"><%= @dashboard.errors.full_messages.first %></div>
|
3
3
|
<% end %>
|
4
4
|
|
5
|
-
<style>
|
6
|
-
.glyphicon-remove {
|
7
|
-
cursor: pointer;
|
8
|
-
color: #d9534f;
|
9
|
-
display: none;
|
10
|
-
}
|
11
|
-
|
12
|
-
li:hover .glyphicon-remove {
|
13
|
-
display: inline;
|
14
|
-
}
|
15
|
-
|
16
|
-
.list-group {
|
17
|
-
cursor: move;
|
18
|
-
}
|
19
|
-
</style>
|
20
|
-
|
21
5
|
<%= form_for @dashboard, url: (@dashboard.persisted? ? dashboard_path(@dashboard, variable_params) : dashboards_path(variable_params)) do |f| %>
|
22
6
|
<div class="form-group">
|
23
7
|
<%= f.label :name %>
|
@@ -1,20 +1,6 @@
|
|
1
1
|
<% blazer_title @dashboard.name %>
|
2
2
|
|
3
|
-
<
|
4
|
-
function submitIfCompleted($form) {
|
5
|
-
var completed = true;
|
6
|
-
$form.find("input[name], select").each( function () {
|
7
|
-
if ($(this).val() == "") {
|
8
|
-
completed = false;
|
9
|
-
}
|
10
|
-
});
|
11
|
-
if (completed) {
|
12
|
-
$form.submit();
|
13
|
-
}
|
14
|
-
}
|
15
|
-
</script>
|
16
|
-
|
17
|
-
<div style="position: fixed; top: 0; left: 0; right: 0; background-color: whitesmoke; height: 60px; z-index: 1001;">
|
3
|
+
<div class="topbar">
|
18
4
|
<div class="container">
|
19
5
|
<div class="row" style="padding-top: 13px;">
|
20
6
|
<div class="col-sm-9">
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
<%= form_for @query, url: (@query.persisted? ? query_path(@query, variable_params) : queries_path(variable_params)), html: {class: "the_form", autocomplete: "off"} do |f| %>
|
6
6
|
<div class="row">
|
7
|
-
<div class="col-xs-8">
|
7
|
+
<div id="statement-box" class="col-xs-8">
|
8
8
|
<div class= "form-group">
|
9
9
|
<%= f.hidden_field :statement %>
|
10
10
|
<div id="editor-container">
|
@@ -16,7 +16,7 @@
|
|
16
16
|
<%= link_to "Back", :back %>
|
17
17
|
</div>
|
18
18
|
<%= f.select :data_source, Blazer.data_sources.values.map { |ds| [ds.name, ds.id] }, {}, class: ("hide" if Blazer.data_sources.size == 1), style: "width: 140px;" %>
|
19
|
-
<div id="tables" style="display: inline-block; width:
|
19
|
+
<div id="tables" style="display: inline-block; width: 250px; margin-right: 10px;" class="hide">
|
20
20
|
<%= render partial: "tables" %>
|
21
21
|
</div>
|
22
22
|
<script>
|
@@ -26,7 +26,8 @@
|
|
26
26
|
updatePreviewSelect();
|
27
27
|
$("#query_data_source").selectize().change(updatePreviewSelect);
|
28
28
|
</script>
|
29
|
-
<%= link_to "Run", "#", class: "btn btn-info", id: "run", style: "vertical-align: top;" %>
|
29
|
+
<%= link_to "Run", "#", class: "btn btn-info", id: "run", style: "vertical-align: top; width: 70px;" %>
|
30
|
+
<%= link_to "Cancel", "#", class: "btn btn-danger hide", id: "cancel", style: "vertical-align: top; width: 70px;" %>
|
30
31
|
</div>
|
31
32
|
</div>
|
32
33
|
<div class="col-xs-4">
|
@@ -124,26 +125,45 @@
|
|
124
125
|
editor.focus();
|
125
126
|
|
126
127
|
var error_line = null;
|
127
|
-
var
|
128
|
+
var runningQuery;
|
128
129
|
var params = <%= raw blazer_json_escape(variable_params.to_json) %>;
|
129
130
|
var previewStatement = <%= raw blazer_json_escape(Hash[Blazer.data_sources.map { |k, v| [k, v.preview_statement] }].to_json) %>;
|
130
131
|
|
131
|
-
|
132
|
+
|
133
|
+
function queryDone() {
|
134
|
+
$("#run").removeClass("hide")
|
135
|
+
$("#cancel").addClass("hide")
|
136
|
+
}
|
137
|
+
|
138
|
+
$("#cancel").click( function (e) {
|
139
|
+
e.preventDefault()
|
140
|
+
|
141
|
+
cancelQuery(runningQuery)
|
142
|
+
queryDone()
|
143
|
+
|
144
|
+
$("#results").html("")
|
145
|
+
})
|
146
|
+
|
147
|
+
$("#run").click( function (e) {
|
132
148
|
e.preventDefault();
|
133
149
|
|
150
|
+
$(this).addClass("hide")
|
151
|
+
$("#cancel").removeClass("hide")
|
152
|
+
|
134
153
|
if (error_line) {
|
135
154
|
editor.getSession().removeGutterDecoration(error_line - 1, "error");
|
136
155
|
error_line = null;
|
137
156
|
}
|
138
157
|
|
139
158
|
$("#results").html('<p class="text-muted">Loading...</p>');
|
140
|
-
if (xhr) {
|
141
|
-
xhr.abort();
|
142
|
-
}
|
143
159
|
|
144
160
|
var data = $.extend({}, params, {statement: getSQL(), data_source: $("#query_data_source").val()});
|
145
161
|
|
146
|
-
|
162
|
+
runningQuery = {};
|
163
|
+
|
164
|
+
runQuery(data, function (data) {
|
165
|
+
queryDone()
|
166
|
+
|
147
167
|
$("#results").html(data);
|
148
168
|
|
149
169
|
error_line = getErrorLine();
|
@@ -153,18 +173,17 @@
|
|
153
173
|
editor.gotoLine(error_line, 0, true);
|
154
174
|
editor.focus();
|
155
175
|
}
|
156
|
-
})
|
176
|
+
}, function (data) {
|
177
|
+
// TODO show error
|
178
|
+
queryDone()
|
179
|
+
}, runningQuery);
|
157
180
|
});
|
158
181
|
|
159
|
-
if ($("#query_statement").val() != "") {
|
160
|
-
$("#run").click();
|
161
|
-
}
|
162
|
-
|
163
182
|
$(document).on("change", "#table_names", function () {
|
164
183
|
var val = $(this).val();
|
165
184
|
if (val.length > 0) {
|
166
185
|
var dataSource = $("#query_data_source").val();
|
167
|
-
editor.setValue(previewStatement[dataSource].replace("{table}", val));
|
186
|
+
editor.setValue(previewStatement[dataSource].replace("{table}", val), 1);
|
168
187
|
$("#run").click();
|
169
188
|
}
|
170
189
|
});
|
@@ -1,18 +1,22 @@
|
|
1
1
|
<div id="queries">
|
2
2
|
<div id="header" style="margin-bottom: 20px;">
|
3
|
-
<div class="
|
4
|
-
<%= link_to "
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
<div class="pull-right">
|
4
|
+
<%= link_to "All", root_path, class: params[:filter] != "mine" ? "active" : nil, style: "margin-right: 40px;" %>
|
5
|
+
<%= link_to "Mine", root_path(filter: "mine"), class: params[:filter] == "mine" ? "active" : nil, style: "margin-right: 40px;" %>
|
6
|
+
<div class="btn-group">
|
7
|
+
<%= link_to "New Query", new_query_path, class: "btn btn-info" %>
|
8
|
+
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
9
|
+
<span class="caret"></span>
|
10
|
+
<span class="sr-only">Toggle Dropdown</span>
|
11
|
+
</button>
|
12
|
+
<ul class="dropdown-menu">
|
13
|
+
<li><%= link_to "Dashboards", dashboards_path %></li>
|
14
|
+
<li><%= link_to "Checks", checks_path %></li>
|
15
|
+
<li role="separator" class="divider"></li>
|
16
|
+
<li><%= link_to "New Dashboard", new_dashboard_path %></li>
|
17
|
+
<li><%= link_to "New Check", new_check_path %></li>
|
18
|
+
</ul>
|
19
|
+
</div>
|
16
20
|
</div>
|
17
21
|
<input type="text" placeholder="Start typing a query or person" style="width: 300px; display: inline-block;" autofocus=true class="search form-control" />
|
18
22
|
</div>
|
@@ -55,7 +59,7 @@
|
|
55
59
|
}
|
56
60
|
</script>
|
57
61
|
|
58
|
-
<% if @
|
62
|
+
<% if @more %>
|
59
63
|
<p id="loading" class="text-muted">Loading...</p>
|
60
64
|
<script>
|
61
65
|
$.getJSON("<%= queries_path %>", function (data) {
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% @schema.each do |table| %>
|
2
|
+
<h4>
|
3
|
+
<%= table[:table] %>
|
4
|
+
<% if table[:schema] != "public" %>
|
5
|
+
<small><%= table[:schema] %></small>
|
6
|
+
<% end %>
|
7
|
+
</h4>
|
8
|
+
<table class="table" style="max-width: 500px;">
|
9
|
+
<tbody>
|
10
|
+
<% table[:columns].each do |column| %>
|
11
|
+
<tr>
|
12
|
+
<td style="width: 60%;"><%= column[:name] %></td>
|
13
|
+
<td class="text-muted"><%= column[:data_type] %></td>
|
14
|
+
</tr>
|
15
|
+
<% end %>
|
16
|
+
</tbody>
|
17
|
+
</table>
|
18
|
+
<% end %>
|
@@ -1,20 +1,6 @@
|
|
1
1
|
<% blazer_title @query.name %>
|
2
2
|
|
3
|
-
<
|
4
|
-
function submitIfCompleted($form) {
|
5
|
-
var completed = true;
|
6
|
-
$form.find("input[name], select").each( function () {
|
7
|
-
if ($(this).val() == "") {
|
8
|
-
completed = false;
|
9
|
-
}
|
10
|
-
});
|
11
|
-
if (completed) {
|
12
|
-
$form.submit();
|
13
|
-
}
|
14
|
-
}
|
15
|
-
</script>
|
16
|
-
|
17
|
-
<div style="position: fixed; top: 0; left: 0; right: 0; background-color: whitesmoke; height: 60px; z-index: 1001;">
|
3
|
+
<div class="topbar">
|
18
4
|
<div class="container">
|
19
5
|
<div class="row" style="padding-top: 13px;">
|
20
6
|
<div class="col-sm-9">
|
data/config/routes.rb
CHANGED
@@ -44,6 +44,11 @@ module Blazer
|
|
44
44
|
result.rows.map(&:first)
|
45
45
|
end
|
46
46
|
|
47
|
+
def schema
|
48
|
+
result = data_source.run_statement(connection_model.send(:sanitize_sql_array, ["SELECT table_schema, table_name, column_name, data_type, ordinal_position FROM information_schema.columns WHERE table_schema IN (?) ORDER BY 1, 2", schemas]))
|
49
|
+
result.rows.group_by { |r| [r[0], r[1]] }.map { |k, vs| {schema: k[0], table: k[1], columns: vs.sort_by { |v| v[4].to_i }.map { |v| {name: v[2], data_type: v[3]} }} }
|
50
|
+
end
|
51
|
+
|
47
52
|
def preview_statement
|
48
53
|
"SELECT * FROM {table} LIMIT 10"
|
49
54
|
end
|
data/lib/blazer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blazer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -154,6 +154,7 @@ files:
|
|
154
154
|
- app/views/blazer/queries/home.html.erb
|
155
155
|
- app/views/blazer/queries/new.html.erb
|
156
156
|
- app/views/blazer/queries/run.html.erb
|
157
|
+
- app/views/blazer/queries/schema.html.erb
|
157
158
|
- app/views/blazer/queries/show.html.erb
|
158
159
|
- app/views/layouts/blazer/application.html.erb
|
159
160
|
- blazer.gemspec
|