arql 0.1.30

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,40 @@
1
+ require_relative 'lib/arql/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "arql"
5
+ spec.version = Arql::VERSION
6
+ spec.authors = ["Liu Xiang"]
7
+ spec.email = ["liuxiang921@gmail.com"]
8
+
9
+ spec.summary = %{Rails ActiveRecord + Pry is the best SQL query editor}
10
+ spec.description = %{Use ActiveRecord and Pry as your favorite SQL query editor.}
11
+ spec.homepage = "https://github.com/lululau/arql"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency 'mysql2', '~> 0.5.3'
27
+ # spec.add_dependency 'pg', '>= 0.18', '< 2.0'
28
+ spec.add_dependency 'sqlite3', '~> 1.4'
29
+ # spec.add_dependency 'activerecord-sqlserver-adapter'
30
+ # spec.add_dependency 'activerecord-oracle_enhanced-adapter'
31
+ spec.add_dependency 'activerecord', '~> 6.0.3'
32
+ spec.add_dependency 'activesupport', '~> 6.0.3'
33
+ spec.add_dependency 'net-ssh-gateway', '~> 2.0.0'
34
+ spec.add_dependency 'pry', '~> 0.13.1'
35
+ spec.add_dependency 'pry-byebug', '~> 3.9.0'
36
+ spec.add_dependency 'pry-doc', '~> 1.1.0'
37
+ spec.add_dependency 'rainbow', '~> 3.0.0'
38
+ spec.add_dependency 'terminal-table', '~> 1.8.0'
39
+ spec.add_dependency 'table_print', '~> 1.5.6'
40
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "arql"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ArqlSetsidWrrapper = File.dirname(File.absolute_path(__FILE__)) + '/arql_setsid_wrapper'
4
+
5
+ require "arql"
6
+
7
+ Arql::Cli.start
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Process.setsid
4
+
5
+ exec(*ARGV)
@@ -0,0 +1,12 @@
1
+ require 'table_print'
2
+ require "arql/version"
3
+ require 'arql/id'
4
+ require 'arql/multi_io'
5
+ require 'arql/ext'
6
+ require "arql/repl"
7
+ require "arql/ssh_proxy"
8
+ require "arql/app"
9
+ require "arql/cli"
10
+
11
+ module Arql
12
+ end
@@ -0,0 +1,137 @@
1
+ require 'net/ssh/gateway'
2
+
3
+ module Arql
4
+ class App
5
+
6
+ class << self
7
+ attr_accessor :log_io, :env
8
+
9
+ def config
10
+ @@effective_config
11
+ end
12
+ end
13
+
14
+ def initialize(options)
15
+ require 'active_support/all'
16
+ require 'active_record'
17
+ require "arql/connection"
18
+ require "arql/definition"
19
+ @options = options
20
+ App.env = @options.env
21
+ Connection.open(connect_options)
22
+ @definition = Definition.new(effective_config)
23
+ load_initializer!
24
+ end
25
+
26
+ def connect_options
27
+ connect_conf = effective_config.slice(:adapter, :host, :username,
28
+ :password, :database, :encoding,
29
+ :pool, :port, :socket)
30
+ if effective_config[:ssh].present?
31
+ connect_conf.merge!(start_ssh_proxy!)
32
+ end
33
+
34
+ connect_conf
35
+ end
36
+
37
+ def load_initializer!
38
+ return unless effective_config[:initializer]
39
+ initializer_file = File.expand_path(effective_config[:initializer])
40
+ unless File.exists?(initializer_file)
41
+ STDERR.puts "Specified initializer file not found, #{effective_config[:initializer]}"
42
+ exit(1)
43
+ end
44
+ load(initializer_file)
45
+ end
46
+
47
+ def start_ssh_proxy!
48
+ ssh_config = effective_config[:ssh]
49
+ local_ssh_proxy_port = Arql::SSHProxy.connect(ssh_config.slice(:host, :user, :port, :password).merge(
50
+ forward_host: effective_config[:host],
51
+ forward_port: effective_config[:port],
52
+ local_port: ssh_config[:local_port]))
53
+ {
54
+ host: '127.0.0.1',
55
+ port: local_ssh_proxy_port
56
+ }
57
+ end
58
+
59
+ def config
60
+ @config ||= YAML.load(IO.read(File.expand_path(@options.config_file))).with_indifferent_access
61
+ end
62
+
63
+ def selected_config
64
+ if @options.env.present? && !config[@options.env].present?
65
+ STDERR.puts "Specified ENV `#{@options.env}' not exists"
66
+ end
67
+ if env = @options.env
68
+ config[env]
69
+ else
70
+ {}
71
+ end
72
+ end
73
+
74
+ def effective_config
75
+ @@effective_config ||= nil
76
+ unless @@effective_config
77
+ @@effective_config = selected_config.deep_merge(@options.to_h)
78
+ if @@effective_config[:adapter].blank?
79
+ @@effective_config[:adapter] = 'sqlite3'
80
+ end
81
+ @@effective_config[:database] = File.expand_path(@@effective_config[:database]) if @@effective_config[:adapter] == 'sqlite3'
82
+ end
83
+ @@effective_config
84
+ end
85
+
86
+ def run!
87
+ show_sql if should_show_sql?
88
+ write_sql if should_write_sql?
89
+ append_sql if should_append_sql?
90
+ if effective_config[:code].present?
91
+ eval(effective_config[:code])
92
+ elsif effective_config[:args].present?
93
+ effective_config[:args].each { |rb| load(rb) }
94
+ elsif STDIN.isatty
95
+ run_repl!
96
+ else
97
+ eval(STDIN.read)
98
+ end
99
+ end
100
+
101
+ def run_repl!
102
+ Repl.new
103
+ end
104
+
105
+ def should_show_sql?
106
+ effective_config[:show_sql]
107
+ end
108
+
109
+ def should_write_sql?
110
+ effective_config[:write_sql]
111
+ end
112
+
113
+ def should_append_sql?
114
+ effective_config[:append_sql]
115
+ end
116
+
117
+ def show_sql
118
+ App.log_io ||= MultiIO.new
119
+ ActiveRecord::Base.logger = Logger.new(App.log_io)
120
+ App.log_io << STDOUT
121
+ end
122
+
123
+ def write_sql
124
+ write_sql_file = effective_config[:write_sql]
125
+ App.log_io ||= MultiIO.new
126
+ ActiveRecord::Base.logger = Logger.new(App.log_io)
127
+ App.log_io << File.new(write_sql_file, 'w')
128
+ end
129
+
130
+ def append_sql
131
+ write_sql_file = effective_config[:append_sql]
132
+ App.log_io ||= MultiIO.new
133
+ ActiveRecord::Base.logger = Logger.new(App.log_io)
134
+ App.log_io << File.new(write_sql_file, 'a')
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,141 @@
1
+ require 'optparse'
2
+ require 'ostruct'
3
+
4
+ module Arql
5
+ class Cli
6
+ class << self
7
+ def start
8
+ parse_options!
9
+ App.new(@options).run!
10
+ end
11
+
12
+ def parse_options!
13
+ @options = OpenStruct.new(config_file: default_config_file,
14
+ initializer: default_initializer,
15
+ ssh: {})
16
+
17
+
18
+ OptionParser.new do |opts|
19
+ opts.banner = <<~EOF
20
+ Usage: arql [options] [ruby file]
21
+
22
+ If neither [ruby file] nor -e option specified, and STDIN is not a tty, a Pry REPL will be launched,
23
+ otherwise the specified ruby file or -e option value or ruby code read from STDIN will be run, and no REPL launched
24
+
25
+ EOF
26
+
27
+ opts.on('-cCONFIG_FILE', '--conf=CONFIG_FILE', 'Specify config file, default is $HOME/.arql.yml, or $HOME/.arql.d/init.yml.') do |config_file|
28
+ @options.config_file = config_file
29
+ end
30
+
31
+ opts.on('-iINITIALIZER', '--initializer=INITIALIZER', 'Specify initializer ruby file, default is $HOME/.arql.rb, or $HOME/.arql.d/init.rb.') do |initializer|
32
+ @options.initializer = initializer
33
+ end
34
+
35
+ opts.on('-eENVIRON', '--env=ENVIRON', 'Specify config environment.') do |env|
36
+ @options.env = env
37
+ end
38
+
39
+ opts.on('-aDB_ADAPTER', '--db-adapter=DB_ADAPTER', 'Specify database Adapter, default is mysql2') do |db_adapter|
40
+ @options.dapter = db_adapter
41
+ end
42
+
43
+ opts.on('-hDB_HOST', '--db-host=DB_HOST', 'Specify database host') do |db_host|
44
+ @options.host = db_host
45
+ end
46
+
47
+ opts.on('-pDB_PORT', '--db-port=DB_PORT', 'Specify database port') do |db_port|
48
+ @options.port = db_port.to_i
49
+ end
50
+
51
+ opts.on('-dDB_NAME', '--db-name=DB_NAME', 'Specify database name') do |db_name|
52
+ @options.database = db_name
53
+ end
54
+
55
+ opts.on('-uDB_USER', '--db-user=DB_USER', 'Specify database user') do |db_user|
56
+ @options.username = db_user
57
+ end
58
+
59
+ opts.on('-PDB_PASSWORD', '--db-password=DB_PASSWORD', 'Specify database password') do |db_password|
60
+ @options.password = db_password
61
+ end
62
+
63
+ opts.on('-n', '--db-encoding=DB_ENCODING', 'Specify database encoding, default is utf8') do |db_encoding|
64
+ @options.encoding = db_encoding
65
+ end
66
+
67
+ opts.on('-o', '--db-pool=DB_POOL', 'Specify database pool size, default is 5') do |db_pool|
68
+ @options.pool = db_pool
69
+ end
70
+
71
+ opts.on('-HSSH_HOST', '--ssh-host=SSH_HOST', 'Specify SSH host') do |ssh_host|
72
+ @options.ssh[:host] = ssh_host
73
+ end
74
+
75
+ opts.on('-OSSH_PORT', '--ssh-port=SSH_PORT', 'Specify SSH port') do |ssh_port|
76
+ @options.ssh[:port] = ssh_port.to_i
77
+ end
78
+
79
+ opts.on('-USSH_USER', '--ssh-user=SSH_USER', 'Specify SSH user') do |ssh_user|
80
+ @options.ssh[:user] = ssh_user
81
+ end
82
+
83
+ opts.on('-WSSH_PASSWORD', '--ssh-password=SSH_PASSWORD', 'Specify SSH password') do |ssh_password|
84
+ @options.ssh[:password] = ssh_password
85
+ end
86
+
87
+ opts.on('-LSSH_LOCAL_PORT', '--ssh-local-port=SSH_LOCAL_PORT', 'Specify local SSH proxy port') do |local_port|
88
+ @options.ssh[:local_port] = local_port.to_i
89
+ end
90
+
91
+ opts.on('-ECODE', '--eval=CODE', 'evaluate CODE') do |code|
92
+ @options.code = code
93
+ end
94
+
95
+ opts.on('-S', '--show-sql', 'Show SQL on STDOUT') do
96
+ @options.show_sql = true
97
+ end
98
+
99
+ opts.on('-wOUTOUT', '--write-sql=OUTPUT', 'Write SQL to OUTPUT file') do |file|
100
+ @options.write_sql = file
101
+ end
102
+
103
+ opts.on('-AOUTPUT', '--append-sql=OUTPUT', 'Append SQL to OUTPUT file') do |file|
104
+ @options.append_sql = file
105
+ end
106
+
107
+ opts.on('-V', '--version', 'Prints version') do
108
+ puts "ARQL #{Arql::VERSION}"
109
+ exit
110
+ end
111
+
112
+ opts.on('', '--help', 'Prints this help') do
113
+ puts opts
114
+ exit
115
+ end
116
+
117
+ end.parse!
118
+
119
+ @options.args = ARGV
120
+ end
121
+
122
+ def default_config_file
123
+ conf = File.expand_path('~/.arql.yml')
124
+ return conf if File.file?(conf)
125
+ conf = File.expand_path('~/.arql.yaml')
126
+ return conf if File.file?(conf)
127
+ conf = File.expand_path('~/.arql.d/init.yml')
128
+ return conf if File.file?(conf)
129
+ conf = File.expand_path('~/.arql.d/init.yaml')
130
+ return conf if File.file?(conf)
131
+ end
132
+
133
+ def default_initializer
134
+ conf = File.expand_path('~/.arql.rb')
135
+ return conf if File.file?(conf)
136
+ conf = File.expand_path('~/.arql.d/init.rb')
137
+ return conf if File.file?(conf)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,9 @@
1
+ require 'arql/commands/info'
2
+ require 'arql/commands/models'
3
+ require 'arql/commands/table'
4
+ require 'arql/commands/reconnect'
5
+ require 'arql/commands/redefine'
6
+ require 'arql/commands/show_sql'
7
+
8
+ module Arql::Commands
9
+ end
@@ -0,0 +1,52 @@
1
+ require 'rainbow'
2
+
3
+ module Arql::Commands
4
+ module Info
5
+ class << self
6
+ def db_info
7
+ <<~EOF
8
+
9
+ Database Connection Information:
10
+
11
+ Active: #{color_boolean(ActiveRecord::Base.connection.active?)}
12
+ Host: #{Arql::App.config[:host]}
13
+ Port: #{Arql::App.config[:port]}
14
+ Username: #{Arql::App.config[:username]}
15
+ Password: #{(Arql::App.config[:password] || '').gsub(/./, '*')}
16
+ Database: #{Arql::App.config[:database]}
17
+ Adapter: #{Arql::App.config[:adapter]}
18
+ Encoding: #{Arql::App.config[:encoding]}
19
+ Pool Size: #{Arql::App.config[:pool]}
20
+ EOF
21
+ end
22
+
23
+ def ssh_info
24
+ <<~EOF
25
+
26
+ SSH Connection Information:
27
+
28
+ Active: #{color_boolean(Arql::SSHProxy.active?)}
29
+ Host: #{Arql::App.config[:ssh][:host]}
30
+ Port: #{Arql::App.config[:ssh][:port]}
31
+ Username: #{Arql::App.config[:ssh][:user]}
32
+ Password: #{(Arql::App.config[:ssh][:password] || '').gsub(/./, '*')}
33
+ Local Port: #{Arql::SSHProxy.local_ssh_proxy_port}
34
+ EOF
35
+ end
36
+
37
+ private
38
+ def color_boolean(bool)
39
+ if bool
40
+ Rainbow('TRUE').green
41
+ else
42
+ Rainbow('FALSE').red
43
+ end
44
+ end
45
+ end
46
+
47
+ Pry.commands.block_command 'info' do
48
+ puts Info::db_info
49
+ puts Info::ssh_info if Arql::App.config[:ssh].present?
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,40 @@
1
+ require 'terminal-table'
2
+
3
+ module Arql::Commands
4
+ module Models
5
+ class << self
6
+ def models
7
+ t = []
8
+ t << ['Table Name', 'Model Class', 'Abbr']
9
+ t << nil
10
+ Arql::Definition.models.each do |definition|
11
+ t << [definition[:table], definition[:model].name, definition[:abbr] || '']
12
+ end
13
+ t
14
+ end
15
+
16
+ def models_table
17
+ Terminal::Table.new do |t|
18
+ models.each { |row| t << (row || :separator) }
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ Pry.commands.block_command 'm' do
25
+ puts
26
+ puts Models::models_table
27
+ end
28
+
29
+ Pry.commands.alias_command 'l', 'm'
30
+ end
31
+
32
+ module Kernel
33
+ def models
34
+ Arql::Commands::Models::models
35
+ end
36
+
37
+ def tables
38
+ models
39
+ end
40
+ end