arql 0.3.3 → 0.3.7

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: 9d10b12fd753e5e8970108008da89ed6dc25b0fd0a920e5a4d4ca52e1bfeed41
4
- data.tar.gz: 0b47045c868b4897b0fd0f4efbb59bc66257f572b04295f3d25a90fe3f633f0d
3
+ metadata.gz: 3a74b566a319ba4437d0f30010fe958105d8dd0d2c129aa4f8546ca4855ec15e
4
+ data.tar.gz: 97f1813e455787ccd8ef9394cde51cc4a2459769427cae004f89386db77ba528
5
5
  SHA512:
6
- metadata.gz: 5e7833f356b11d0b3840f5afddb4a6582173b67e4033a428cdb82c7933648921c090922a1168e01b4675d4cf49c4011de4b78bfe27cb0f93a98934527676538d
7
- data.tar.gz: b198b84d7b3cd9767bfb5f7a55f57e5bbed39a387fa080536c7c9ccfc65db16efa3d8b5bac51cb1d0801d04c14e102b723bd871f6ddff9872b27e62fedb1dd9b
6
+ metadata.gz: a6016fbb6da3857724030da6ce875e0a5889f50207026e71af1a9cc12a867165afaf6b9c4f6465750c91b01a0bbbae7f439507bfb9b02d7f1b854227793e7ffb
7
+ data.tar.gz: d4995846d815847ad229ca4bef01ebc722fcf0c9b4575c42f77229e0480b76e78df6a47518e14b10a2ff06c6616dae9e1aa8e962060ab40ee8eaa923e22c056c
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /.idea/
data/.solargraph.yml ADDED
@@ -0,0 +1,10 @@
1
+ require:
2
+ - actioncable
3
+ - actionmailer
4
+ - actionpack
5
+ - actionview
6
+ - activejob
7
+ - activemodel
8
+ - activerecord
9
+ - activestorage
10
+ - activesupport
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- arql (0.3.3)
4
+ arql (0.3.7)
5
5
  activerecord (>= 6.0.3, < 6.2.0)
6
6
  activesupport (~> 6.0.3)
7
7
  caxlsx (~> 3.0.2)
@@ -40,7 +40,7 @@ GEM
40
40
  coderay (1.1.3)
41
41
  composite_primary_keys (12.0.10)
42
42
  activerecord (~> 6.0.0)
43
- concurrent-ruby (1.1.9)
43
+ concurrent-ruby (1.1.10)
44
44
  htmlentities (4.3.4)
45
45
  i18n (1.8.11)
46
46
  concurrent-ruby (~> 1.0)
@@ -53,7 +53,7 @@ GEM
53
53
  net-ssh (6.1.0)
54
54
  net-ssh-gateway (2.0.0)
55
55
  net-ssh (>= 4.0.0)
56
- nokogiri (1.13.0-x86_64-darwin)
56
+ nokogiri (1.13.4-x86_64-darwin)
57
57
  racc (~> 1.4)
58
58
  pry (0.13.1)
59
59
  coderay (~> 1.1)
@@ -82,7 +82,7 @@ GEM
82
82
  webrick (1.7.0)
83
83
  yard (0.9.27)
84
84
  webrick (~> 1.7.0)
85
- zeitwerk (2.5.3)
85
+ zeitwerk (2.5.4)
86
86
 
87
87
  PLATFORMS
88
88
  ruby
data/lib/arql/app.rb CHANGED
@@ -29,8 +29,14 @@ module Arql
29
29
  App.env = @options.env
30
30
  App.connect_options = connect_options
31
31
  Connection.open(App.connect_options)
32
+ print "Defining models..."
32
33
  @definition = Definition.new(effective_config)
34
+ print "\u001b[2K"
35
+ puts "\rModels defined"
36
+ print "Running initializers..."
33
37
  load_initializer!
38
+ print "\u001b[2K"
39
+ puts "\rInitializers loaded"
34
40
  App.instance = self
35
41
  end
36
42
 
@@ -0,0 +1,33 @@
1
+ module Arql::Commands
2
+ module Sandbox
3
+ class << self
4
+ attr_accessor :enabled
5
+
6
+ @sandbox_callback = proc do
7
+ begin_transaction(joinable: false)
8
+ end
9
+
10
+ def enter
11
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback(:checkout, :after, &@sandbox_callback)
12
+ ActiveRecord::Base.connection.begin_transaction(joinable: false)
13
+ @enabled = true
14
+ end
15
+
16
+ def quit
17
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.skip_callback(:checkout, :after, &@sandbox_callback)
18
+ @enabled = false
19
+
20
+ puts "begin_transaction callbacks removed."
21
+ puts "You still have open %d transactions open, don't forget commit or rollback them." % ActiveRecord::Base.connection.open_transactions if ActiveRecord::Base.connection.open_transactions > 0
22
+ end
23
+ end
24
+
25
+ Pry.commands.block_command 'sandbox-enter' do
26
+ Sandbox.enter
27
+ end
28
+
29
+ Pry.commands.block_command 'sandbox-quit' do
30
+ Sandbox.quit
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,46 @@
1
+ require 'arql/vd'
2
+
3
+ module Arql::Commands
4
+ module VD
5
+ class << self
6
+ def get_table_name(name)
7
+ name = name.to_s
8
+ return name if name =~ /^[a-z]/
9
+ if Object.const_defined?(name)
10
+ klass = Object.const_get(name)
11
+ return klass.table_name if klass < ActiveRecord::Base
12
+ end
13
+ name
14
+ end
15
+
16
+ def table_info_vd(table_name)
17
+ Arql::VD.new do |vd|
18
+ table_info(table_name).each { |row| vd << row }
19
+ end
20
+ end
21
+
22
+ def table_info(table_name)
23
+ t = []
24
+ t << ['PK', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
25
+ connection = ::ActiveRecord::Base.connection
26
+ connection.columns(table_name).each do |column|
27
+ pk = if [connection.primary_key(table_name)].flatten.include?(column.name)
28
+ 'Y'
29
+ else
30
+ ''
31
+ end
32
+ t << [pk, column.name, column.sql_type,
33
+ column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
34
+ column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
35
+ column.null, column.comment || '']
36
+ end
37
+ t
38
+ end
39
+ end
40
+
41
+ Pry.commands.block_command 'vd' do |name|
42
+ table_name = VD::get_table_name(name)
43
+ VD::table_info_vd(table_name)
44
+ end
45
+ end
46
+ end
data/lib/arql/commands.rb CHANGED
@@ -4,6 +4,8 @@ require 'arql/commands/table'
4
4
  require 'arql/commands/reconnect'
5
5
  require 'arql/commands/redefine'
6
6
  require 'arql/commands/show_sql'
7
+ require 'arql/commands/sandbox'
8
+ require 'arql/commands/vd'
7
9
 
8
10
  module Arql::Commands
9
11
  end
@@ -2,7 +2,10 @@ module Arql
2
2
  class Connection
3
3
  class << self
4
4
  def open(options)
5
+ print "Establishing DB connection to #{options[:host]}:#{options[:port]}"
5
6
  ActiveRecord::Base.establish_connection(options)
7
+ print "\u001b[2K"
8
+ puts "\rDB connection to #{options[:host]}:#{options[:port]} established\n"
6
9
  $C = ActiveRecord::Base.connection
7
10
  $C.define_singleton_method(:dump) do |filename, no_create_db=false|
8
11
  Arql::Mysqldump.new.dump_database(filename, no_create_db)
@@ -1,4 +1,6 @@
1
1
  require 'arql/concerns'
2
+ require 'arql/vd'
3
+
2
4
  module Arql
3
5
  module Extension
4
6
  extend ActiveSupport::Concern
@@ -9,6 +11,15 @@ module Arql
9
11
  }
10
12
  end
11
13
 
14
+ def vd
15
+ VD.new do |vd|
16
+ vd << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
17
+ self.class.connection.columns(self.class.table_name).each do |column|
18
+ vd << [column.name, read_attribute(column.name), column.sql_type, column.comment || '']
19
+ end
20
+ end
21
+ end
22
+
12
23
  def v
13
24
  t = []
14
25
  t << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
@@ -49,6 +60,12 @@ module Arql
49
60
  puts Commands::Table::table_info_table(table_name)
50
61
  end
51
62
 
63
+ def vd
64
+ table_name = Commands::Table::get_table_name(name)
65
+ Commands::VD::table_info_vd(table_name)
66
+ nil
67
+ end
68
+
52
69
  def v
53
70
  table_name = Commands::Table::get_table_name(name)
54
71
  Commands::Table::table_info(table_name)
@@ -91,18 +108,21 @@ module Arql
91
108
  end
92
109
  @@models = []
93
110
  ActiveRecord::Base.connection.tap do |conn|
94
- conn.tables.each do |table_name|
95
- table_comment = conn.table_comment(table_name)
96
- conn.primary_key(table_name).tap do |pkey|
111
+ tables = conn.tables
112
+ comments = conn.table_comment_of_tables(tables)
113
+ primary_keys = conn.primary_keys_of_tables(tables)
114
+ tables.each do |table_name|
115
+ table_comment = comments[table_name]
116
+ primary_keys[table_name].tap do |pkey|
97
117
  table_name.camelize.tap do |const_name|
98
118
  const_name = 'Modul' if const_name == 'Module'
99
119
  const_name = 'Clazz' if const_name == 'Class'
100
120
  Class.new(::ArqlModel) do
101
121
  include Arql::Extension
102
- if pkey.is_a?(Array)
122
+ if pkey.is_a?(Array) && pkey.size > 1
103
123
  self.primary_keys = pkey
104
124
  else
105
- self.primary_key = pkey
125
+ self.primary_key = pkey&.first
106
126
  end
107
127
  self.table_name = table_name
108
128
  self.inheritance_column = nil
@@ -169,18 +189,29 @@ module Arql
169
189
  end.t
170
190
  end
171
191
  end)
172
- conn.tables.each do |table_name|
173
- table_comment = conn.table_comment(table_name)
174
- conn.primary_key(table_name).tap do |pkey|
192
+
193
+ tables = conn.tables
194
+ if conn.adapter_name == 'Mysql2'
195
+ require 'arql/ext/active_record/connection_adapters/abstract_mysql_adapter'
196
+ comments = conn.table_comment_of_tables(tables)
197
+ primary_keys = conn.primary_keys_of_tables(tables)
198
+ else
199
+ comments = tables.map { |t| [t, conn.table_comment(t)] }.to_h
200
+ primary_keys = tables.map { |t| [t, conn.primary_keys(t)] }.to_h
201
+ end
202
+
203
+ tables.each do |table_name|
204
+ table_comment = comments[table_name]
205
+ primary_keys[table_name].tap do |pkey|
175
206
  table_name.camelize.tap do |const_name|
176
207
  const_name = 'Modul' if const_name == 'Module'
177
208
  const_name = 'Clazz' if const_name == 'Class'
178
209
  Class.new(::ArqlModel) do
179
210
  include Arql::Extension
180
- if pkey.is_a?(Array)
211
+ if pkey.is_a?(Array) && pkey.size > 1
181
212
  self.primary_keys = pkey
182
213
  else
183
- self.primary_key = pkey
214
+ self.primary_key = pkey&.first
184
215
  end
185
216
  self.table_name = table_name
186
217
  self.inheritance_column = nil
@@ -229,6 +260,10 @@ module Arql
229
260
  records.t(*attrs, **options)
230
261
  end
231
262
 
263
+ def vd(*attrs, **options)
264
+ records.vd(*attrs, **options)
265
+ end
266
+
232
267
  def v
233
268
  records.v
234
269
  end
@@ -0,0 +1,53 @@
1
+ require 'active_record/connection_adapters/abstract_mysql_adapter'
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ class AbstractMysqlAdapter
6
+
7
+ def extract_schema_qualified_name_of_tables(table_names)
8
+ table_names.map do |string|
9
+ schema, name = string.to_s.scan(/[^`.\s]+|`[^`]*`/)
10
+ schema, name = nil, schema unless name
11
+ [schema, name]
12
+ end
13
+ end
14
+
15
+ def quoted_scope_of_tables(names = nil)
16
+ extract_schema_qualified_name_of_tables(names).map do |(schema, name)|
17
+ scope = {}
18
+ scope[:schema] = schema ? quote(schema) : "database()"
19
+ scope[:name] = quote(name) if name
20
+ scope
21
+ end
22
+ end
23
+
24
+ def primary_keys_of_tables(table_names) # :nodoc:
25
+ raise ArgumentError unless table_names.present?
26
+
27
+ scopes = quoted_scope_of_tables(table_names)
28
+
29
+ res = query(<<~SQL, "SCHEMA")
30
+ SELECT table_name, column_name
31
+ FROM information_schema.statistics
32
+ WHERE index_name = 'PRIMARY'
33
+ AND (table_schema, table_name) in
34
+ (#{scopes.map { |scope| "(#{scope[:schema]}, #{scope[:name]})" }.join(', ')})
35
+ ORDER BY seq_in_index
36
+ SQL
37
+
38
+ res.group_by(&:first).map { |table, vlaues| [table, vlaues.map(&:last)] }.to_h
39
+ end
40
+
41
+ def table_comment_of_tables(table_names) # :nodoc:
42
+ scopes = quoted_scope_of_tables(table_names)
43
+
44
+ query(<<~SQL, "SCHEMA").presence.try(&:to_h)
45
+ SELECT table_name, table_comment
46
+ FROM information_schema.tables
47
+ WHERE (table_schema, table_name) in
48
+ (#{scopes.map { |scope| "(#{scope[:schema]}, #{scope[:name]})" }.join(', ')})
49
+ SQL
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,8 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module PostgreSQL
4
+ module SchemaStatements
5
+ end
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,5 @@
1
+ require 'arql/vd'
2
+
1
3
  class Array
2
4
  def to_insert_sql(batch_size=500)
3
5
  raise 'All element should be an ActiveRecord instance object' unless all? { |e| e.is_a?(ActiveRecord::Base) }
@@ -48,6 +50,33 @@ class Array
48
50
  end
49
51
  end
50
52
 
53
+ def vd(*attrs, **options)
54
+ if (attrs.present? || options.present? && options[:except]) && present? && first.is_a?(ActiveRecord::Base)
55
+ column_names = first.attribute_names.map(&:to_sym)
56
+ attrs = attrs.flat_map { |e| e.is_a?(Regexp) ? column_names.grep(e) : e }.uniq
57
+ if options.present? && options[:except]
58
+ attrs = column_names if attrs.empty?
59
+ if options[:except].is_a?(Regexp)
60
+ attrs.reject! { |e| e =~ options[:except] }
61
+ else
62
+ attrs -= [options[:except]].flatten
63
+ end
64
+ end
65
+
66
+ Arql::VD.new do |vd|
67
+ vd << attrs
68
+ each do |e|
69
+ vd << e.attributes.values_at(*attrs.map(&:to_s))
70
+ end
71
+ end
72
+ else
73
+ Arql::VD.new do |vd|
74
+ v.each { |row| vd << row if row }
75
+ end
76
+ end
77
+ nil
78
+ end
79
+
51
80
  def v
52
81
  return self unless present?
53
82
  t = []
data/lib/arql/multi_io.rb CHANGED
@@ -5,7 +5,14 @@ module Arql
5
5
  end
6
6
 
7
7
  def write(*args)
8
- @targets.each {|t| t.write(*args)}
8
+ @targets.each do |t|
9
+ if t.isatty
10
+ t.write(*args)
11
+ else
12
+ t.write(*(args.map { |str| str.gsub(/\e\[(\d+)m/, '')}))
13
+ end
14
+ t.flush
15
+ end
9
16
  end
10
17
 
11
18
  def close
data/lib/arql/repl.rb CHANGED
@@ -35,7 +35,12 @@ module Arql
35
35
  "(#{obj}:#{nest_level})"
36
36
  end
37
37
  end
38
- "%s#{Rainbow('@').green}%s#{nest_level_prompt} [%d] %s " % [Rainbow('ARQL').red, Rainbow(App.prompt).yellow, pry_instance.input_ring.count, Rainbow('❯').green]
38
+ if Arql::Commands::Sandbox.enabled
39
+ sandbox_indicator = ' [%s] ' % Rainbow('sandbox').green.bright
40
+ else
41
+ sandbox_indicator = ''
42
+ end
43
+ "%s#{Rainbow('@').green}%s%s#{nest_level_prompt} [%d] %s " % [Rainbow('ARQL').red, Rainbow(App.prompt).yellow, sandbox_indicator, pry_instance.input_ring.count, Rainbow('❯').green]
39
44
  end]
40
45
  end
41
46
  end
@@ -8,9 +8,13 @@ module Arql
8
8
  attr_accessor :config, :ssh_gateway, :local_ssh_proxy_port
9
9
 
10
10
  def connect(config)
11
+ print "Establishing SSH connection to #{config[:host]}:#{config[:port]}"
11
12
  @config = config
12
13
  @ssh_gateway = Net::SSH::Gateway.new(config[:host], config[:user], config.slice(:port, :password).symbolize_keys.merge(keepalive: true, keepalive_interval: 30, loop_wait: 1))
13
14
  @local_ssh_proxy_port = @ssh_gateway.open(config[:forward_host], config[:forward_port], config[:local_port])
15
+ print "\u001b[2K"
16
+ puts "\rSSH connection to #{config[:host]}:#{config[:port]} established"
17
+ @local_ssh_proxy_port
14
18
  end
15
19
 
16
20
  def reconnect
data/lib/arql/vd.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'csv'
2
+
3
+ module Arql
4
+ class VD
5
+ COMMAND = 'vd'
6
+
7
+ attr_accessor :rows
8
+
9
+ def initialize
10
+ return unless check_command_installation
11
+ @rows = []
12
+ yield self
13
+ command = "#{COMMAND} -f csv"
14
+ IO.popen(command, 'w+') do |io|
15
+ io.puts(csv)
16
+ io.close_write
17
+ end
18
+ end
19
+
20
+ def <<(row)
21
+ rows << row
22
+ end
23
+
24
+ def csv
25
+ CSV.generate do |csv|
26
+ rows.each do |row|
27
+ csv << row
28
+ end
29
+ end
30
+ end
31
+
32
+ def check_command_installation
33
+ `which #{COMMAND}`
34
+ if $?.exitstatus != 0
35
+ puts "Please install vd (visidata) command, see: https://www.visidata.org/"
36
+ else
37
+ true
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/arql/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Arql
2
- VERSION = "0.3.3"
2
+ VERSION = "0.3.7"
3
3
  end
data/lib/arql.rb CHANGED
@@ -11,6 +11,7 @@ require "arql/ssh_proxy"
11
11
  require "arql/app"
12
12
  require "arql/cli"
13
13
  require "arql/mysqldump"
14
+ require "arql/vd"
14
15
 
15
16
  module Arql
16
17
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Xiang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-13 00:00:00.000000000 Z
11
+ date: 2022-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mysql2
@@ -222,6 +222,7 @@ extensions: []
222
222
  extra_rdoc_files: []
223
223
  files:
224
224
  - ".gitignore"
225
+ - ".solargraph.yml"
225
226
  - CODE_OF_CONDUCT.md
226
227
  - Gemfile
227
228
  - Gemfile.lock
@@ -241,14 +242,18 @@ files:
241
242
  - lib/arql/commands/models.rb
242
243
  - lib/arql/commands/reconnect.rb
243
244
  - lib/arql/commands/redefine.rb
245
+ - lib/arql/commands/sandbox.rb
244
246
  - lib/arql/commands/show_sql.rb
245
247
  - lib/arql/commands/table.rb
248
+ - lib/arql/commands/vd.rb
246
249
  - lib/arql/concerns.rb
247
250
  - lib/arql/concerns/global_data_definition.rb
248
251
  - lib/arql/concerns/table_data_definition.rb
249
252
  - lib/arql/connection.rb
250
253
  - lib/arql/definition.rb
251
254
  - lib/arql/ext.rb
255
+ - lib/arql/ext/active_record/connection_adapters/abstract_mysql_adapter.rb
256
+ - lib/arql/ext/active_record/connection_adapters/postgresql/schema_statements.rb
252
257
  - lib/arql/ext/array.rb
253
258
  - lib/arql/ext/hash.rb
254
259
  - lib/arql/ext/kernel.rb
@@ -261,6 +266,7 @@ files:
261
266
  - lib/arql/repl.rb
262
267
  - lib/arql/ssh_proxy.rb
263
268
  - lib/arql/ssh_proxy_patch.rb
269
+ - lib/arql/vd.rb
264
270
  - lib/arql/version.rb
265
271
  homepage: https://github.com/lululau/arql
266
272
  licenses: