myq 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +45 -3
- data/contrib/completion/_myq +3 -0
- data/lib/myq.rb +3 -2
- data/lib/myq/commands.rb +115 -39
- data/lib/myq/core.rb +251 -0
- data/lib/myq/version.rb +1 -1
- data/myq.gemspec +1 -0
- data/sample/activerecord.erb +3 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8b3fd06c82c8b6f9b0ceaeeda5cb83cda1fc660
|
4
|
+
data.tar.gz: 81876b670a2ad08727a1dcc51b9cdca95661bd48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8de83b6f92794318e946a9016e78c5e208774e696fca4ad1bc69a990c3bdc4a64c01b910274e80c33733dd176e59db1d13acdc9e77f15701148a48d377b17b0c
|
7
|
+
data.tar.gz: f63fcfbc45251d1eeead3f7fedbf3232c3cf6d3de882253f5361e6b694b51cc005fdb365a6640805436a41bfc3afb5d716995eb2bd5c5e1329cac39cff913f4c
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Myq
|
2
2
|
|
3
|
-
|
3
|
+
mysql to json utility
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -18,7 +18,7 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Setting
|
20
20
|
|
21
|
-
Create $HOME/.database.yml
|
21
|
+
Create $HOME/.database.yml(rails format)
|
22
22
|
```yml
|
23
23
|
default:
|
24
24
|
database: test
|
@@ -37,7 +37,49 @@ staging:
|
|
37
37
|
|
38
38
|
## Usage
|
39
39
|
|
40
|
-
|
40
|
+
```bash
|
41
|
+
Commands:
|
42
|
+
myq --dbs # show databases
|
43
|
+
myq --ps # show processlist
|
44
|
+
myq --set -v key=value; -v, --variables=key:value # set global variable
|
45
|
+
myq --template [erb] # generate template by schema info
|
46
|
+
myq -C # mysql console
|
47
|
+
myq -D # mysql dump
|
48
|
+
myq -I [table] # bulk insert json, auto create table!
|
49
|
+
myq -R # mysql restore
|
50
|
+
myq -c [table name] -k [group by keys] # count record, group by keys
|
51
|
+
myq -f [file] # query by sql file
|
52
|
+
myq -l [table name] # show table info
|
53
|
+
myq -q [sql] # inline query
|
54
|
+
myq -s [table name] # sampling query, default limit 10
|
55
|
+
myq -v [like query] # show variables
|
56
|
+
myq create_db [database] # mysql console
|
57
|
+
myq help [COMMAND] # Describe available commands or one specific command
|
58
|
+
myq version # show version
|
59
|
+
|
60
|
+
Options:
|
61
|
+
-p, [--profile=PROFILE] # profile by .database.yml
|
62
|
+
# Default: default
|
63
|
+
-P, [--pretty], [--no-pretty] # pretty print
|
64
|
+
--config, [--config=CONFIG] # config file
|
65
|
+
# Default: /Users/toyama-h/.database.yml
|
66
|
+
```
|
67
|
+
|
68
|
+
## Exsample
|
69
|
+
|
70
|
+
### run query
|
71
|
+
|
72
|
+
```bash
|
73
|
+
$ myq -q "select * from access limit 10"
|
74
|
+
[{"host":"48.189.196.32","user":"-","method":"POST","referer":"-","path":"/search/?c=Games+Sports","size":133,"code":200,"agent":"Mozilla/4.0 (compatible; MSIE ","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"128.24.107.59","user":"-","method":"GET","referer":"-","path":"/category/electronics","size":70,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.1; W","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"144.102.28.67","user":"-","method":"GET","referer":"/category/office","path":"/item/games/4274","size":59,"code":200,"agent":"Mozilla/4.0 (compatible; MSIE ","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"100.129.167.163","user":"-","method":"GET","referer":"/category/books","path":"/item/electronics/4570","size":139,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.0; r","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"132.189.67.199","user":"-","method":"POST","referer":"-","path":"/search/?c=Finance","size":116,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.0) A","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"176.147.148.79","user":"-","method":"GET","referer":"/category/software","path":"/item/jewelry/4592","size":78,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.1; W","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"200.48.189.175","user":"-","method":"GET","referer":"-","path":"/category/software","size":85,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.0; r","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"220.111.122.175","user":"-","method":"GET","referer":"/category/software","path":"/category/networking","size":43,"code":200,"agent":"Mozilla/5.0 (compatible; Googl","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"220.117.150.167","user":"-","method":"GET","referer":"-","path":"/category/electronics","size":109,"code":200,"agent":"Mozilla/4.0 (compatible; MSIE ","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"176.93.131.44","user":"-","method":"POST","referer":"/category/music","path":"/search/?c=Toys","size":60,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.1; W","updated_at":"2014-03-01 19:03:39 +0900"}]
|
75
|
+
```
|
76
|
+
|
77
|
+
### sampling query
|
78
|
+
|
79
|
+
```bash
|
80
|
+
$ myq -s access
|
81
|
+
[{"host":"48.189.196.32","user":"-","method":"POST","referer":"-","path":"/search/?c=Games+Sports","size":133,"code":200,"agent":"Mozilla/4.0 (compatible; MSIE ","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"128.24.107.59","user":"-","method":"GET","referer":"-","path":"/category/electronics","size":70,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.1; W","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"144.102.28.67","user":"-","method":"GET","referer":"/category/office","path":"/item/games/4274","size":59,"code":200,"agent":"Mozilla/4.0 (compatible; MSIE ","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"100.129.167.163","user":"-","method":"GET","referer":"/category/books","path":"/item/electronics/4570","size":139,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.0; r","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"132.189.67.199","user":"-","method":"POST","referer":"-","path":"/search/?c=Finance","size":116,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.0) A","updated_at":"2014-03-01 19:03:38 +0900"},{"host":"176.147.148.79","user":"-","method":"GET","referer":"/category/software","path":"/item/jewelry/4592","size":78,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.1; W","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"200.48.189.175","user":"-","method":"GET","referer":"-","path":"/category/software","size":85,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.0; r","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"220.111.122.175","user":"-","method":"GET","referer":"/category/software","path":"/category/networking","size":43,"code":200,"agent":"Mozilla/5.0 (compatible; Googl","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"220.117.150.167","user":"-","method":"GET","referer":"-","path":"/category/electronics","size":109,"code":200,"agent":"Mozilla/4.0 (compatible; MSIE ","updated_at":"2014-03-01 19:03:39 +0900"},{"host":"176.93.131.44","user":"-","method":"POST","referer":"/category/music","path":"/search/?c=Toys","size":60,"code":200,"agent":"Mozilla/5.0 (Windows NT 6.1; W","updated_at":"2014-03-01 19:03:39 +0900"}]
|
82
|
+
```
|
41
83
|
|
42
84
|
## Contributing
|
43
85
|
|
data/lib/myq.rb
CHANGED
data/lib/myq/commands.rb
CHANGED
@@ -1,74 +1,150 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# coding: utf-8
|
3
3
|
require 'thor'
|
4
|
-
require 'mysql2-cs-bind'
|
5
4
|
require 'yajl'
|
6
|
-
require 'yaml'
|
7
5
|
|
8
6
|
module Myq
|
9
7
|
class Commands < Thor
|
10
|
-
class_option :
|
11
|
-
class_option :
|
12
|
-
class_option :
|
13
|
-
|
14
|
-
class_option :database, aliases: '-d', type: :string, desc: 'database'
|
15
|
-
class_option :profile, aliases: '--pr', type: :string, default: 'default', desc: 'profile by .database.yml'
|
8
|
+
class_option :profile, aliases: '-p', type: :string, default: 'default', desc: 'profile by .database.yml'
|
9
|
+
class_option :pretty, aliases: '-P', type: :boolean, default: false, desc: 'pretty print'
|
10
|
+
class_option :config, aliases: '--config', type: :string, default: "#{ENV['HOME']}/.database.yml", desc: 'config file'
|
11
|
+
map '--ps' => :processlist
|
16
12
|
map '-q' => :query_inline
|
13
|
+
map '-c' => :count
|
17
14
|
map '-f' => :query_file
|
18
15
|
map '-s' => :sample
|
19
|
-
map '-
|
16
|
+
map '-l' => :show_table
|
17
|
+
map '--dbs' => :show_databases
|
18
|
+
map '-v' => :show_variables
|
19
|
+
map '-I' => :bulk_insert_json
|
20
|
+
map '-V' => :version
|
21
|
+
map '--set' => :set_variable
|
22
|
+
map '-C' => :console
|
23
|
+
map '-D' => :dump
|
24
|
+
map '-R' => :restore
|
25
|
+
map '--template' => :template
|
20
26
|
|
21
27
|
def initialize(args = [], options = {}, config = {})
|
22
28
|
super(args, options, config)
|
23
|
-
global_options = config[:shell].base.options
|
24
|
-
|
25
|
-
data = YAML.load_file("#{ENV['HOME']}/.database.yml")[global_options['profile']]
|
26
|
-
host = data['host']
|
27
|
-
username = data['username']
|
28
|
-
password = data['password']
|
29
|
-
database = data['database']
|
30
|
-
port = data['port']
|
31
|
-
else
|
32
|
-
host = global_options['host']
|
33
|
-
username = global_options['username']
|
34
|
-
password = global_options['password']
|
35
|
-
database = global_options['database']
|
36
|
-
port = global_options['port']
|
37
|
-
end
|
38
|
-
@client = Mysql2::Client.new(host: host, username: username, password: password, database: database, port: port)
|
29
|
+
@global_options = config[:shell].base.options
|
30
|
+
@core = Myq::Core.new(get_profile(@global_options))
|
39
31
|
end
|
40
32
|
|
41
|
-
desc
|
33
|
+
desc '-q [sql]', 'inline query'
|
34
|
+
option :interval, type: :numeric, default: 0, aliases: '-i', desc: 'loop interval'
|
42
35
|
def query_inline(query)
|
43
|
-
|
36
|
+
loop do
|
37
|
+
puts_json(@core.query(query))
|
38
|
+
break if options['interval'] == 0
|
39
|
+
sleep options['interval']
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc '-I [table]', 'bulk insert json, auto create table!'
|
44
|
+
option :update_columns, type: :array, aliases: '-u', default: [], desc: 'on duplicate key update columns'
|
45
|
+
def bulk_insert_json(table)
|
46
|
+
data = @core.parse_json(STDIN.read)
|
47
|
+
sql = @core.make_bulk_insert_sql(table, data, options['update_columns'])
|
48
|
+
@core.query_single(sql)
|
44
49
|
end
|
45
50
|
|
46
|
-
desc
|
51
|
+
desc '-f [file]', 'query by sql file'
|
47
52
|
def query_file(file)
|
48
|
-
query(File.read(file))
|
53
|
+
puts_json(@core.query(File.read(file)))
|
49
54
|
end
|
50
55
|
|
51
|
-
desc
|
56
|
+
desc '-s [table name]', 'sampling query, default limit 10'
|
57
|
+
option :where, type: :hash, default: nil, aliases: '-w', desc: 'id'
|
52
58
|
option :limit, type: :numeric, default: 10, aliases: '-n', desc: 'limit count'
|
59
|
+
option :all, type: :boolean, default: false, aliases: '-a', desc: 'all'
|
53
60
|
def sample(table)
|
54
|
-
|
61
|
+
limit = options['all'] ? "" : "limit #{options['limit']}"
|
62
|
+
where = options['where'].nil? ? "" : "where #{options['where'].map{ |k, v| k + ' = ' + v }.join(' and ') }"
|
63
|
+
puts_json(@core.query("select * from #{table} #{where} order by id desc #{limit}"))
|
64
|
+
end
|
65
|
+
|
66
|
+
desc '-c [table name] -k [group by keys]', 'count record, group by keys'
|
67
|
+
option :keys, type: :array, aliases: '-k', default: [], desc: 'group by keys'
|
68
|
+
def count(table)
|
69
|
+
puts_json(@core.count(table, options['keys']))
|
70
|
+
end
|
71
|
+
|
72
|
+
desc '-l [table name]', 'show table info '
|
73
|
+
def show_table(table_name = nil)
|
74
|
+
puts_json(@core.tables(table_name))
|
75
|
+
end
|
76
|
+
|
77
|
+
desc '--dbs', 'show databases'
|
78
|
+
def show_databases
|
79
|
+
puts_json(@core.databases)
|
80
|
+
end
|
81
|
+
|
82
|
+
desc '--ps', 'show processlist'
|
83
|
+
def processlist
|
84
|
+
puts_json(@core.processlist)
|
85
|
+
end
|
86
|
+
|
87
|
+
desc '-v [like query]', 'show variables '
|
88
|
+
def show_variables(like = nil)
|
89
|
+
puts_json(@core.variables(like))
|
90
|
+
end
|
91
|
+
|
92
|
+
desc '--template [erb]', 'show variables '
|
93
|
+
option :output_template, aliases: '-o', type: :string, default: Dir.pwd, desc: 'output directory'
|
94
|
+
option :format, aliases: '--format [camelcase or underscore]', type: :string, default: nil, desc: 'filename format'
|
95
|
+
def template(template_path)
|
96
|
+
@core.render_template(template_path, options['output_template'], options['format'])
|
97
|
+
end
|
98
|
+
|
99
|
+
desc '-C', 'mysql console'
|
100
|
+
def console
|
101
|
+
@core.console
|
102
|
+
end
|
103
|
+
|
104
|
+
desc '-D', 'mysql dump'
|
105
|
+
def dump(filepath = "#{@profile['database']}.dump")
|
106
|
+
@core.dump(filepath)
|
107
|
+
end
|
108
|
+
|
109
|
+
desc '-R', 'mysql restore'
|
110
|
+
def restore(filepath = "#{@profile['database']}.dump")
|
111
|
+
@core.restore(filepath)
|
112
|
+
end
|
113
|
+
|
114
|
+
desc 'create_db [database]', 'create database'
|
115
|
+
def create_db(database)
|
116
|
+
@core.create_database_utf8(database)
|
117
|
+
end
|
118
|
+
|
119
|
+
desc '--set -v key=value;', 'set global variable'
|
120
|
+
option :variables, type: :hash, aliases: '-v', required: true, desc: 'set variables'
|
121
|
+
def set_variable(key = nil, value = nil)
|
122
|
+
options['variables'].each do |k, v|
|
123
|
+
@core.query("SET GLOBAL #{k}=#{v}")
|
124
|
+
end
|
55
125
|
end
|
56
126
|
|
57
|
-
desc
|
127
|
+
desc 'version', 'show version'
|
58
128
|
def version
|
59
129
|
puts VERSION
|
130
|
+
puts `mysql -V`
|
60
131
|
end
|
61
132
|
|
62
133
|
private
|
63
134
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
135
|
+
def get_profile(options)
|
136
|
+
if File.exist?(options['config'])
|
137
|
+
profile = YAML.load_file(options['config'])[options['profile']]
|
138
|
+
else
|
139
|
+
puts "please create #{ENV['HOME']}/.database.yml"
|
140
|
+
exit 1
|
71
141
|
end
|
142
|
+
profile
|
143
|
+
end
|
144
|
+
|
145
|
+
def puts_json(object)
|
146
|
+
puts Yajl::Encoder.encode(object, pretty: @global_options['pretty'])
|
72
147
|
end
|
148
|
+
|
73
149
|
end
|
74
150
|
end
|
data/lib/myq/core.rb
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
require 'mysql2-cs-bind'
|
4
|
+
require 'active_support/core_ext/string'
|
5
|
+
require 'yaml'
|
6
|
+
require 'yajl'
|
7
|
+
|
8
|
+
module Myq
|
9
|
+
class Core
|
10
|
+
|
11
|
+
def initialize(profile)
|
12
|
+
@profile = profile
|
13
|
+
@client = Mysql2::Client.new(profile)
|
14
|
+
end
|
15
|
+
|
16
|
+
def make_bulk_insert_sql(table, data, update_columns)
|
17
|
+
first = data.class == Array ? data.first : data
|
18
|
+
auto_create_table(table, first)
|
19
|
+
columns = table_info(table).to_a
|
20
|
+
values_array = []
|
21
|
+
if data.class == Array
|
22
|
+
data.each do |record|
|
23
|
+
values_array << to_value_string(columns, record)
|
24
|
+
end
|
25
|
+
else
|
26
|
+
values_array << to_value_string(columns, data)
|
27
|
+
end
|
28
|
+
sql = %Q{
|
29
|
+
INSERT INTO #{table}
|
30
|
+
(#{columns.map { |column| "\`" + column['COLUMN_NAME'] + "\`" }.join(',')})
|
31
|
+
VALUES
|
32
|
+
#{values_array.join(",\n")}
|
33
|
+
#{make_duplicate_key_update_sql(update_columns)}
|
34
|
+
}
|
35
|
+
sql
|
36
|
+
end
|
37
|
+
|
38
|
+
def make_duplicate_key_update_sql(update_columns)
|
39
|
+
return "" if update_columns.empty?
|
40
|
+
updates = []
|
41
|
+
update_columns.each do |update_column|
|
42
|
+
updates << "#{update_column}=VALUES(\`#{update_column}\`)"
|
43
|
+
end
|
44
|
+
"ON DUPLICATE KEY UPDATE " + updates.join(', ')
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_value_string(columns, record)
|
48
|
+
values_string = columns.map do |column|
|
49
|
+
generate_value(record, column)
|
50
|
+
end.join(',')
|
51
|
+
'(' + values_string + ')'
|
52
|
+
end
|
53
|
+
|
54
|
+
def query(query)
|
55
|
+
result = []
|
56
|
+
query.split(';').each do |sql|
|
57
|
+
next if sql.blank?
|
58
|
+
res = @client.xquery(sql)
|
59
|
+
next if res.nil?
|
60
|
+
res.each do |record|
|
61
|
+
result << record
|
62
|
+
end
|
63
|
+
end
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
def count(table, keys)
|
68
|
+
select_query = keys.empty? ? '' : "#{keys.join(',')},"
|
69
|
+
group_by_query = keys.empty? ? '' : "group by #{keys.join(',')}"
|
70
|
+
query(%Q{select #{select_query} count(*) as count from #{table} #{group_by_query} order by count desc})
|
71
|
+
end
|
72
|
+
|
73
|
+
def query_single(query)
|
74
|
+
begin
|
75
|
+
res = @client.xquery(query)
|
76
|
+
rescue => e
|
77
|
+
puts "\n#{e.message}\n#{e.backtrace.join("\n")}"
|
78
|
+
puts query
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def auto_create_table(table, hash)
|
83
|
+
res = table_info(table)
|
84
|
+
if res.size == 0
|
85
|
+
create_table_sql = %Q{CREATE TABLE #{table} (\n#{generate_create_table(hash)}\n)}
|
86
|
+
query(create_table_sql)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_database_utf8(database)
|
91
|
+
@client.xquery("CREATE DATABASE #{database} CHARACTER SET 'UTF8'")
|
92
|
+
end
|
93
|
+
|
94
|
+
def tables(table_name)
|
95
|
+
if table_name.nil?
|
96
|
+
query('SELECT * FROM INFORMATION_SCHEMA.TABLES')
|
97
|
+
else
|
98
|
+
query("show full columns from #{table_name}")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def databases
|
103
|
+
query('show databases')
|
104
|
+
end
|
105
|
+
|
106
|
+
def processlist
|
107
|
+
query('SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST')
|
108
|
+
end
|
109
|
+
|
110
|
+
def table_info(table)
|
111
|
+
@client.xquery("SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '#{table}'")
|
112
|
+
end
|
113
|
+
|
114
|
+
def generate_value(record, column)
|
115
|
+
value = record[column['COLUMN_NAME']]
|
116
|
+
return 'NULL' if value.nil?
|
117
|
+
if value.class == String
|
118
|
+
# is_time_format
|
119
|
+
time = to_time_or_nil(value)
|
120
|
+
if !time.nil?
|
121
|
+
return "'" + time.strftime('%Y-%m-%d %H:%M:%S') + "'"
|
122
|
+
end
|
123
|
+
max_length = column['CHARACTER_MAXIMUM_LENGTH']
|
124
|
+
return "'" + Mysql2::Client.escape(value) + "'" if max_length.nil?
|
125
|
+
value = value.size > max_length ? value.slice(0, max_length) : value
|
126
|
+
return "'" + Mysql2::Client.escape(value) + "'"
|
127
|
+
elsif value.class == Hash
|
128
|
+
escaped = Mysql2::Client.escape(Yajl::Encoder.encode(value))
|
129
|
+
return "'" + escaped + "'"
|
130
|
+
end
|
131
|
+
"'#{value}'"
|
132
|
+
end
|
133
|
+
|
134
|
+
def generate_create_table(hash)
|
135
|
+
results = hash.map do |k, v|
|
136
|
+
generate_alter(k, v)
|
137
|
+
end
|
138
|
+
results << 'id integer NOT NULL auto_increment PRIMARY KEY' unless hash.keys.map(&:downcase).include?('id')
|
139
|
+
results.compact.join(",\n")
|
140
|
+
end
|
141
|
+
|
142
|
+
def generate_alter(k, v)
|
143
|
+
if v.nil?
|
144
|
+
"\`#{k}\` varchar(255)"
|
145
|
+
elsif k =~ /^id$/i
|
146
|
+
"\`id\` integer NOT NULL auto_increment PRIMARY KEY"
|
147
|
+
elsif v.class == String
|
148
|
+
to_time_or_nil(v).nil? ? "\`#{k}\` varchar(255)" : "\`#{k}\` datetime"
|
149
|
+
elsif v.class == Fixnum
|
150
|
+
"\`#{k}\` integer"
|
151
|
+
elsif v.class == Array
|
152
|
+
"\`#{k}\` text"
|
153
|
+
elsif v.class == Hash
|
154
|
+
"\`#{k}\` text"
|
155
|
+
elsif v.respond_to?(:strftime)
|
156
|
+
"\`#{k}\` datetime"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def to_time_or_nil(value)
|
161
|
+
return nil if value.slice(0, 4) !~ /^[0-9][0-9][0-9][0-9]/
|
162
|
+
begin
|
163
|
+
time = value.to_time
|
164
|
+
time.to_i >= 0 ? time : nil
|
165
|
+
rescue => e
|
166
|
+
nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def parse_json(buffer)
|
171
|
+
begin
|
172
|
+
data = Yajl::Parser.parse(buffer)
|
173
|
+
rescue => e
|
174
|
+
data = []
|
175
|
+
buffer.split("\n").each do |line|
|
176
|
+
data << Yajl::Parser.parse(line)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
data
|
180
|
+
end
|
181
|
+
|
182
|
+
def variables(like = nil)
|
183
|
+
if like.nil?
|
184
|
+
query('SHOW VARIABLES')
|
185
|
+
else
|
186
|
+
query("SHOW VARIABLES LIKE '%#{like}%'")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def render_template(template_path = nil, output_template, format)
|
191
|
+
system 'mkdir -p ' + File.dirname(output_template)
|
192
|
+
database = @profile['database']
|
193
|
+
tables = @client.xquery("SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = '#{database}'")
|
194
|
+
tables.each do |table|
|
195
|
+
table_name = table['TABLE_NAME']
|
196
|
+
sql = %Q{SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA = '#{database}' and TABLE_NAME = '#{table_name}'}
|
197
|
+
columns = @client.xquery(sql)
|
198
|
+
filepath = sprintf(output_template, parse_table(table_name, format))
|
199
|
+
filewrite = File.open(filepath,'w')
|
200
|
+
filewrite.puts ERB.new(File.read(template_path)).result(binding)
|
201
|
+
filewrite.close
|
202
|
+
puts "create #{table_name} => #{filepath}"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def console
|
207
|
+
cmd = <<-EOF
|
208
|
+
mysql -A\
|
209
|
+
-u #{@profile['username']}\
|
210
|
+
-h #{@profile['host']}\
|
211
|
+
-p #{@profile['database']}\
|
212
|
+
--password='#{@profile['password']}'
|
213
|
+
EOF
|
214
|
+
system(cmd)
|
215
|
+
end
|
216
|
+
|
217
|
+
def dump(filepath = "#{@profile['database']}.dump")
|
218
|
+
cmd = <<-EOF
|
219
|
+
mysqldump \
|
220
|
+
-u #{@profile['username']}\
|
221
|
+
-h #{@profile['host']}\
|
222
|
+
-p #{@profile['database']}\
|
223
|
+
--password='#{@profile['password']}'\
|
224
|
+
--default-character-set=binary\
|
225
|
+
> #{filepath}
|
226
|
+
EOF
|
227
|
+
system(cmd)
|
228
|
+
end
|
229
|
+
|
230
|
+
def restore(filepath = "#{@profile['database']}.dump")
|
231
|
+
cmd = <<-EOF
|
232
|
+
mysql -A\
|
233
|
+
-u #{@profile['username']}\
|
234
|
+
-h #{@profile['host']}\
|
235
|
+
-p #{@profile['database']}\
|
236
|
+
--password='#{@profile['password']}'\
|
237
|
+
--default-character-set=binary\
|
238
|
+
-f < #{filepath}
|
239
|
+
EOF
|
240
|
+
system(cmd)
|
241
|
+
end
|
242
|
+
|
243
|
+
private
|
244
|
+
|
245
|
+
def parse_table(table_name, format)
|
246
|
+
return table_name if format.nil?
|
247
|
+
eval("table_name.#{format}")
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
end
|
data/lib/myq/version.rb
CHANGED
data/myq.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: myq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- toyama0919
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: Command-line MYSQL TO JSON processor.
|
84
98
|
email:
|
85
99
|
- toyama0919@gmail.com
|
@@ -94,10 +108,13 @@ files:
|
|
94
108
|
- README.md
|
95
109
|
- Rakefile
|
96
110
|
- bin/myq
|
111
|
+
- contrib/completion/_myq
|
97
112
|
- lib/myq.rb
|
98
113
|
- lib/myq/commands.rb
|
114
|
+
- lib/myq/core.rb
|
99
115
|
- lib/myq/version.rb
|
100
116
|
- myq.gemspec
|
117
|
+
- sample/activerecord.erb
|
101
118
|
homepage: ''
|
102
119
|
licenses:
|
103
120
|
- MIT
|