sqlui 0.1.16 → 0.1.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7c438724dd4d58432da2908650a10bb82c3452a2faf4f0560c5dd23a8fd6d66
4
- data.tar.gz: 949a64296520f3e7fcfec48ae1a4cc8b4a4056184d88a88ca52b5813b1ad8064
3
+ metadata.gz: f951e672b477e0fd4882c1aa4e42472975ac07fa6a2955eb4430bc1018ea6165
4
+ data.tar.gz: d8e7da6fe289ed3e94322a3ea3d5ce461356cbfa73e2e2732bab9001a8d3af24
5
5
  SHA512:
6
- metadata.gz: ab6348bdcbeb1b2dfd7e38c206b7d72bf388f28ae992e15c40823b00db1bc3bdfb705cc3764373ca0f1de053b32ea546f84bdacf99328b5b6def0f9aea40954e
7
- data.tar.gz: a55564765cd9c90fe47ef06d521aefde3bc78f903527cd4a49b6817267364ff6cd609d47b645a9508c382fcc1798b355b414b12ea861782038b538dbaa90a861
6
+ metadata.gz: 6769e3ee3c0b5330ca0b1ac1433370756838cec3187f0bd9822308704d31ee1608592199acb9b622edba8d45146c557e413d42c0a060bb9ace9b7653b43ad54c
7
+ data.tar.gz: 4ef70417125cdb931c5f6edba2ef7986be7bda22f0f27c362d7bea97df81752133493e9507b941cbfe51261fa4e77aca85f4838354805a97d88e64f0240e452d
data/.version CHANGED
@@ -1 +1 @@
1
- 0.1.16
1
+ 0.1.18
data/app/environment.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Parses and provides access to environment variables.
1
4
  class Environment
2
5
  SERVER_ENV = ENV.fetch('SERVER_ENV', 'development').to_sym
3
6
  SERVER_PORT = ENV.fetch('SERVER_PORT', 8080)
@@ -17,4 +20,4 @@ class Environment
17
20
  def self.server_port
18
21
  SERVER_PORT
19
22
  end
20
- end
23
+ end
data/app/server.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erb'
2
4
  require 'json'
3
5
  require 'mysql2'
@@ -12,14 +14,16 @@ if ARGV.include?('-v') || ARGV.include?('--version')
12
14
  end
13
15
 
14
16
  raise 'you must specify a configuration file' unless ARGV.size == 1
15
- raise "configuration file does not exist" unless File.exist?(ARGV[0])
17
+ raise 'configuration file does not exist' unless File.exist?(ARGV[0])
16
18
 
19
+ # SQLUI Sinatra server.
17
20
  class Server < Sinatra::Base
18
21
  set :logging, true
19
22
  set :bind, '0.0.0.0'
20
23
  set :port, Environment.server_port
21
24
  set :env, Environment.server_env
22
25
 
26
+ # A MySQL client. This needs to go away.
23
27
  class Client
24
28
  def initialize(params)
25
29
  @params = params
@@ -35,30 +39,30 @@ class Server < Sinatra::Base
35
39
  end
36
40
  end
37
41
 
38
- config = YAML.load(ERB.new(File.read(ARGV[0])).result)
42
+ config = YAML.safe_load(ERB.new(File.read(ARGV[0])).result)
39
43
  saved_path_root = config['saved_path']
40
- client_map = config['databases'].values.map do |database_config|
44
+ client_map = config['databases'].values.to_h do |database_config|
41
45
  client_params = {
42
- host: database_config['db_host'],
43
- port: database_config['db_port'] || 3306,
44
- username: database_config['db_username'],
45
- password: database_config['db_password'],
46
- database: database_config['db_database'],
47
- read_timeout: 10, # seconds
48
- write_timeout: 0, # seconds
46
+ host: database_config['db_host'],
47
+ port: database_config['db_port'] || 3306,
48
+ username: database_config['db_username'],
49
+ password: database_config['db_password'],
50
+ database: database_config['db_database'],
51
+ read_timeout: 10, # seconds
52
+ write_timeout: 0, # seconds
49
53
  connect_timeout: 5 # seconds
50
54
  }
51
55
  client = Client.new(client_params)
52
56
  [
53
- database_config['url_path'],
57
+ database_config['url_path'],
54
58
  ::SQLUI.new(
55
- client: client,
59
+ client: client,
56
60
  table_schema: database_config['db_database'],
57
- name: database_config['name'],
58
- saved_path: File.join(saved_path_root, database_config['saved_path'])
61
+ name: database_config['name'],
62
+ saved_path: File.join(saved_path_root, database_config['saved_path'])
59
63
  )
60
64
  ]
61
- end.to_h
65
+ end
62
66
 
63
67
  get '/-/health' do
64
68
  status 200
@@ -66,7 +70,7 @@ class Server < Sinatra::Base
66
70
  end
67
71
 
68
72
  get '/db/?' do
69
- erb :databases, :locals => {:databases => config['databases']}
73
+ erb :databases, locals: { databases: config['databases'] }
70
74
  end
71
75
 
72
76
  get '/db/:database' do
@@ -76,7 +80,7 @@ class Server < Sinatra::Base
76
80
  get '/db/:database/:route' do
77
81
  response = client_map[params[:database]].get(params)
78
82
  status response[:status]
79
- headers "Content-Type": response[:content_type]
83
+ headers 'Content-Type': response[:content_type]
80
84
  body response[:body]
81
85
  end
82
86
 
@@ -84,7 +88,7 @@ class Server < Sinatra::Base
84
88
  post_body = JSON.parse(request.body.read)
85
89
  response = client_map[params[:database]].post(params.merge(post_body))
86
90
  status response[:status]
87
- headers "Content-Type": response[:content_type]
91
+ headers 'Content-Type': response[:content_type]
88
92
  body response[:body]
89
93
  end
90
94
 
data/app/sqlui.rb CHANGED
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'uri'
3
5
  require 'set'
4
6
 
7
+ # Main SQLUI class responsible for producing web content. This class needs to die.
5
8
  class SQLUI
6
9
  MAX_ROWS = 1_000
7
10
 
8
- def initialize(client:, table_schema: nil, name:, saved_path:, max_rows: MAX_ROWS)
11
+ def initialize(client:, name:, saved_path:, table_schema: nil, max_rows: MAX_ROWS)
9
12
  @client = client
10
13
  @table_schema = table_schema
11
14
  @name = name
@@ -65,35 +68,33 @@ class SQLUI
65
68
  end
66
69
 
67
70
  def query_file(params)
68
- if params['file']
69
- sql = File.read("#{@saved_path}/#{params['file']}")
70
- execute_query(sql).tap { |r| r[:file] = params[:file] }
71
- else
72
- raise 'missing file param'
73
- end
71
+ raise 'missing file param' unless params['file']
72
+
73
+ sql = File.read("#{@saved_path}/#{params['file']}")
74
+ execute_query(sql).tap { |r| r[:file] = params[:file] }
74
75
  end
75
76
 
76
77
  def metadata
77
- @metadata ||= load_metadata
78
+ load_metadata
78
79
  end
79
80
 
80
81
  def load_metadata
81
82
  result = {
82
- server: @name,
83
+ server: @name,
83
84
  schemas: {},
84
- saved: Dir.glob("#{@saved_path}/*.sql").sort.map do |path|
85
+ saved: Dir.glob("#{@saved_path}/*.sql").map do |path|
85
86
  {
86
- filename: File.basename(path),
87
+ filename: File.basename(path),
87
88
  description: File.readlines(path).take_while { |l| l.start_with?('--') }.map { |l| l.sub(/^-- */, '') }.join
88
89
  }
89
90
  end
90
91
  }
91
92
 
92
- if @table_schema
93
- where_clause = "where table_schema = '#{@table_schema}'"
94
- else
95
- where_clause = "where table_schema not in('mysql', 'sys', 'information_schema', 'performance_schema')"
96
- end
93
+ where_clause = if @table_schema
94
+ "where table_schema = '#{@table_schema}'"
95
+ else
96
+ "where table_schema not in('mysql', 'sys', 'information_schema', 'performance_schema')"
97
+ end
97
98
  column_result = @client.query(
98
99
  <<~SQL
99
100
  select
@@ -129,9 +130,7 @@ class SQLUI
129
130
  end
130
131
  columns = result[:schemas][table_schema][:tables][table_name][:columns]
131
132
  column_name = row[:column_name]
132
- unless columns[column_name]
133
- columns[column_name] = {}
134
- end
133
+ columns[column_name] = {} unless columns[column_name]
135
134
  column = columns[column_name]
136
135
  column[:name] = column_name
137
136
  column[:data_type] = row[:data_type]
@@ -142,11 +141,11 @@ class SQLUI
142
141
  column[:extra] = row[:extra]
143
142
  end
144
143
 
145
- if @table_schema
146
- where_clause = "where table_schema = '#{@table_schema}'"
147
- else
148
- where_clause = "where table_schema not in('mysql', 'sys', 'information_schema', 'performance_schema')"
149
- end
144
+ where_clause = if @table_schema
145
+ "where table_schema = '#{@table_schema}'"
146
+ else
147
+ "where table_schema not in('mysql', 'sys', 'information_schema', 'performance_schema')"
148
+ end
150
149
  stats_result = @client.query(
151
150
  <<~SQL
152
151
  select
@@ -168,9 +167,7 @@ class SQLUI
168
167
  table_name = row[:table_name]
169
168
  indexes = tables[table_name][:indexes]
170
169
  index_name = row[:index_name]
171
- unless indexes[index_name]
172
- indexes[index_name] = {}
173
- end
170
+ indexes[index_name] = {} unless indexes[index_name]
174
171
  index = indexes[index_name]
175
172
  column_name = row[:column_name]
176
173
  index[column_name] = {}
@@ -186,13 +183,13 @@ class SQLUI
186
183
 
187
184
  def execute_query(sql)
188
185
  result = @client.query(sql)
189
- rows = result.map { |row| row.values }
186
+ rows = result.map(&:values)
190
187
  columns = result.first&.keys || []
191
188
  column_types = columns.map { |_| 'string' }
192
189
  unless rows.empty?
193
190
  maybe_non_null_column_value_exemplars = columns.each_with_index.map do |_, index|
194
- row = rows.find do |row|
195
- !row[index].nil?
191
+ row = rows.find do |current|
192
+ !current[index].nil?
196
193
  end
197
194
  row.nil? ? nil : row[index]
198
195
  end
@@ -210,22 +207,24 @@ class SQLUI
210
207
  end
211
208
  end
212
209
  {
213
- query: sql,
214
- columns: columns,
210
+ query: sql,
211
+ columns: columns,
215
212
  column_types: column_types,
216
- total_rows: rows.size,
217
- rows: rows.take(@max_rows)
213
+ total_rows: rows.size,
214
+ rows: rows.take(@max_rows)
218
215
  }
219
216
  end
220
217
 
221
218
  def find_query_at_cursor(sql, cursor)
222
219
  parts_with_ranges = []
223
220
  sql.scan(/[^;]*;[ \n]*/) { |part| parts_with_ranges << [part, 0, part.size] }
224
- parts_with_ranges.inject(0) do |pos, part_with_range|
225
- part_with_range[1] += pos
226
- part_with_range[2] += pos
221
+ parts_with_ranges.inject(0) do |pos, current|
222
+ current[1] += pos
223
+ current[2] += pos
227
224
  end
228
- part_with_range = parts_with_ranges.find { |part_with_range| cursor >= part_with_range[1] && cursor < part_with_range[2] } || parts_with_ranges[-1]
225
+ part_with_range = parts_with_ranges.find do |current|
226
+ cursor >= current[1] && cursor < current[2]
227
+ end || parts_with_ranges[-1]
229
228
  part_with_range[0]
230
229
  end
231
230
  end
@@ -5,11 +5,13 @@
5
5
  <style>
6
6
  body {
7
7
  font-family: Helvetica;
8
+ margin: 0px;
8
9
  }
9
10
 
10
11
  h1 {
11
12
  font-size: 30px;
12
- margin-bottom: 30px;
13
+ margin: 10px;
14
+
13
15
  }
14
16
 
15
17
  .database a {
@@ -20,8 +22,6 @@
20
22
 
21
23
  .database h2 {
22
24
  margin: 0px;
23
- margin-top: 10px;
24
- margin-bottom: 0px;
25
25
  font-size: 20px;
26
26
  font-weight: bold;
27
27
  }
@@ -29,11 +29,12 @@
29
29
  .database p {
30
30
  margin: 0px;
31
31
  margin-top: 10px;
32
- padding-bottom: 20px;
33
32
  font-size: 16px;
34
33
  }
35
34
 
36
35
  .database {
36
+ margin: 0px;
37
+ padding: 10px;
37
38
  cursor: pointer;
38
39
  border-bottom: 1px solid #eeeeee;
39
40
  }
@@ -52,11 +53,11 @@
52
53
  <h1>Databases</h1>
53
54
  <% databases.values.each do |database| %>
54
55
  <div class="database" onclick="window.location='<%= "/db/#{database['url_path']}/app" %>'">
55
- <h2><%= database['name'] %></h2>
56
- <a href="/db/<%= database['url_path'] %>/app">query</a>
57
- <a href="/db/<%= database['url_path'] %>/app?tab=saved">saved</a>
58
- <a href="/db/<%= database['url_path'] %>/app?tab=structure">structure</a>
59
- <p>
56
+ <h2 class='name'><%= database['name'] %></h2>
57
+ <a class='query-link' href="/db/<%= database['url_path'] %>/app">query</a>
58
+ <a class='saved-link' href="/db/<%= database['url_path'] %>/app?tab=saved">saved</a>
59
+ <a class='structure-link' href="/db/<%= database['url_path'] %>/app?tab=structure">structure</a>
60
+ <p class='description'>
60
61
  <%= database['description'] %>
61
62
  </p>
62
63
  </div>
data/bin/sqlui CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require_relative '../app/server'