dba 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.
@@ -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: []