sqlui 0.1.16 → 0.1.18

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: 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'