myq 0.0.1 → 1.0.0
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 +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
|