dba 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DBA::RowEditor
4
+ def initialize(row_parser)
5
+ @row_parser = row_parser
6
+
7
+ @editor = ENV['EDITOR']
8
+ end
9
+
10
+ def edit(hash)
11
+ io = IO.popen(@editor, 'w+')
12
+
13
+ printer = DBA::Printer.new(io)
14
+ printer.print_row(hash)
15
+
16
+ io.close_write
17
+
18
+ output = io.read
19
+
20
+ io.close
21
+
22
+ @row_parser.parse(output)
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bigdecimal'
4
+ require 'time'
5
+
6
+ class DBA::RowParser
7
+ def initialize(table_schema)
8
+ @table_schema = table_schema
9
+ end
10
+
11
+ def parse(string)
12
+ string.strip.split("\n").each_with_object({}) do |line, hash|
13
+ key, value = line.split(/:\s*/, 2)
14
+
15
+ column_name = key.to_sym
16
+
17
+ hash[column_name] = value_parse(column_name, value)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ PARSERS = {
24
+ :integer => method(:Integer),
25
+ :date => Date.method(:parse),
26
+ :datetime => Time.method(:parse),
27
+ :decimal => method(:BigDecimal)
28
+ }
29
+
30
+ def value_parse(column_name, value)
31
+ if value == 'NULL'
32
+ nil
33
+ elsif parser = PARSERS[@table_schema.column_type(column_name)]
34
+ parser.call(value)
35
+ else
36
+ value
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ class DBA::Sample < DBA::Command
2
+ def call(table, column = nil)
3
+ self.table_name = table
4
+
5
+ column_name = column.to_sym if column
6
+
7
+ random_rows = database[table_name].order(random_function)
8
+
9
+ if column_name
10
+ random_rows.distinct.select(column_name).limit(20).each do |row|
11
+ puts row[column_name]
12
+ end
13
+ else
14
+ random_rows.first(3).each do |row|
15
+ printer.print(row)
16
+ printer.print_line
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def random_function
24
+ if defined?(Sequel::Mysql2) && database.is_a?(Sequel::Mysql2::Database)
25
+ return Sequel.function(:rand)
26
+ end
27
+
28
+ Sequel.function(:random)
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ class DBA::Schema < DBA::TableCommand
2
+ def visit(table_name)
3
+ printer.print_schema(table_name, database.schema(table_name))
4
+ end
5
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBA::Shell
4
+ extend self
5
+
6
+ def run(args=ARGV)
7
+ print_usage if args.empty? || args == ['--help']
8
+
9
+ command_name = args.shift
10
+
11
+ command = commands[command_name]
12
+
13
+ if command.nil?
14
+ raise DBA::Error, "#{command_name} is not a valid command"
15
+ end
16
+
17
+ command = DBA.const_get(command)
18
+
19
+ arity = command.instance_method(:call).arity
20
+
21
+ if arity >= 0 && args.size != arity
22
+ raise DBA::Error, "incorrect number of args (given #{args.size}, expected #{arity})"
23
+ end
24
+
25
+ database = DBA::Database.connect
26
+
27
+ command = command.new(database)
28
+ command.call(*args)
29
+ rescue DBA::Error => exception
30
+ print_error(exception.message)
31
+ end
32
+
33
+ private
34
+
35
+ def commands
36
+ {
37
+ 'diff' => :Diff,
38
+ 'edit' => :Edit,
39
+ 'find' => :Find,
40
+ 'indexes' => :Indexes,
41
+ 'pull' => :Pull,
42
+ 'sample' => :Sample,
43
+ 'schema' => :Schema,
44
+ 'tables' => :Tables
45
+ }
46
+ end
47
+
48
+ def command_parameters
49
+ commands.transform_values do |name|
50
+ DBA.const_get(name).instance_method(:call).parameters
51
+ end
52
+ end
53
+
54
+ def program_name
55
+ File.basename($0)
56
+ end
57
+
58
+ def print_usage
59
+ printer = DBA::Printer.new(STDERR)
60
+ printer.print_usage(program_name, command_parameters)
61
+
62
+ Kernel::exit(1)
63
+ end
64
+
65
+ def print_error(message)
66
+ printer = DBA::Printer.new(STDERR)
67
+ printer.print_error(message)
68
+
69
+ Kernel::exit(1)
70
+ end
71
+ end
@@ -0,0 +1,11 @@
1
+ class DBA::TableCommand < DBA::Command
2
+ def call(table = nil)
3
+ if table
4
+ self.table_name = table
5
+
6
+ visit(table_name)
7
+ else
8
+ database.tables.sort.each { |name| visit(name) }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ class DBA::TableSchema
2
+ def initialize(database, table_name)
3
+ @schema = database.schema(table_name)
4
+
5
+ @column_type_hash = @schema.each_with_object({}) do |(column_name, column_info), hash|
6
+ hash[column_name] = column_info[:type]
7
+ end
8
+ end
9
+
10
+ def primary_key
11
+ @schema.each do |column_name, column_info|
12
+ return column_name if column_info[:primary_key]
13
+ end
14
+
15
+ return nil
16
+ end
17
+
18
+ def column_type(column_name)
19
+ @column_type_hash.fetch(column_name)
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ class DBA::Tables < DBA::Command
2
+ def call
3
+ database.tables.sort.each do |name|
4
+ row_count = database[name].count
5
+
6
+ printer.print_table(name, row_count)
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dba
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tim Craft
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-10-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: zeitwerk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: '2.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: sequel
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: pastel
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ description: A developer tool for working with development databases
62
+ email:
63
+ - mail@timcraft.com
64
+ executables:
65
+ - dba
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - LICENSE.txt
70
+ - README.md
71
+ - bin/dba
72
+ - dba.gemspec
73
+ - lib/dba.rb
74
+ - lib/dba/command.rb
75
+ - lib/dba/database.rb
76
+ - lib/dba/diff.rb
77
+ - lib/dba/edit.rb
78
+ - lib/dba/find.rb
79
+ - lib/dba/indexes.rb
80
+ - lib/dba/printer.rb
81
+ - lib/dba/pull.rb
82
+ - lib/dba/row_command.rb
83
+ - lib/dba/row_editor.rb
84
+ - lib/dba/row_parser.rb
85
+ - lib/dba/sample.rb
86
+ - lib/dba/schema.rb
87
+ - lib/dba/shell.rb
88
+ - lib/dba/table_command.rb
89
+ - lib/dba/table_schema.rb
90
+ - lib/dba/tables.rb
91
+ homepage: https://github.com/readysteady/dba
92
+ licenses:
93
+ - GPL-3.0
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 2.3.0
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubygems_version: 3.0.3
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: See description
114
+ test_files: []