psql-cm 0.0.1

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.
data/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2009 Wayne E. Seguin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ # PostgreSQL Change Management Tool
2
+
3
+
4
+
data/bin/psql-cm ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'psql-cm'
4
+ require 'psql-cm/cli'
5
+
6
+ ::PSQLCM::CLI.parse!(ARGV)
7
+
8
+ ::PSQLCM.run!(ARGV.shift)
9
+
10
+
@@ -0,0 +1,114 @@
1
+ module PSQLCM
2
+ class << self
3
+ def verbose(message)
4
+ $stdout.puts message if (config.verbose || config.debug)
5
+ end
6
+
7
+ def debug(message)
8
+ $stdout.puts message if config.debug
9
+ end
10
+
11
+ def halt!(message)
12
+ $stderr.puts message
13
+ exit 1
14
+ end
15
+
16
+ def config
17
+ require 'ostruct'
18
+ @config ||= OpenStruct.new
19
+ end # def self.config
20
+
21
+ def databases
22
+ @databases = db.
23
+ exec("SELECT datname as name FROM pg_database WHERE datname !~ 'template*|postgres';").
24
+ map {|row| row["name"]}
25
+
26
+ debug "databases> #{@databases}"
27
+ unless config.databases.to_a.empty?
28
+ @databases.select!{ |name| config.databases.include?(name) }
29
+ end
30
+ @databases
31
+ end
32
+
33
+ def schemas
34
+ @schemas = db.
35
+ exec("SELECT nspname as name FROM pg_namespace WHERE nspname !~ '^pg_.*|information_schema';").
36
+ map{|row| row["name"]}
37
+ debug "schemas> #{@schemas}"
38
+ @schemas
39
+ end
40
+
41
+ def tree
42
+ return @tree if @tree
43
+ @tree = {}
44
+ databases.each do |name|
45
+ @config.connection["dbname"] = name and reconnect!
46
+ @tree[name] = {}
47
+ schemas.each do |schema|
48
+ @tree[name][schema] = ['base.sql', 'cm.sql']
49
+ end
50
+ end
51
+ debug "tree> tree: #{@tree}"
52
+ @tree
53
+ end
54
+
55
+ def generate!
56
+ unless config.sql_path
57
+ $stdout.puts "Warning: --sql-path was not set, defaulting to $PWD/sql."
58
+ config.sql_path = "#{ENV["PWD"]}/sql"
59
+ end
60
+
61
+ FileUtils.mkdir(config.sql_path) unless File.directory?(config.sql_path)
62
+
63
+ debug "generate> sql_path: #{config.sql_path}"
64
+ Dir.chdir(config.sql_path) do
65
+ tree.each_pair do |database, hash|
66
+ debug "generate> database: #{database}"
67
+
68
+ File.directory?(File.join(config.sql_path,database)) or
69
+ FileUtils.mkdir(File.join(config.sql_path,database))
70
+
71
+ hash.each_pair do |schema, files|
72
+ debug "generate> schema: #{schema}"
73
+ File.directory?(File.join(config.sql_path,database,schema)) or
74
+ FileUtils.mkdir(File.join(config.sql_path,database,schema))
75
+
76
+ base_file = File.join(config.sql_path,database,schema,'base.sql')
77
+ cm_file = File.join(config.sql_path,database,schema,'cm.sql')
78
+
79
+ FileUtils.touch(base_file)
80
+ FileUtils.touch(cm_file)
81
+
82
+ command = "pg_dump --schema-only --no-owner --schema=#{schema} "
83
+ if File.size(base_file) > 0
84
+ command += "--file=#{cm_file} --table=psql_cm "
85
+ else
86
+ command += "--file=#{base_file} --exclude-table=psql_cm "
87
+ end
88
+ command += "#{database}"
89
+ debug "generate> #{command}"
90
+
91
+ %x[#{command}]
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ def run!(action = config.action, parent_id = config.parent_id)
98
+ case action
99
+ when "console"
100
+ ::PSQLCM.debug "Starting Console"
101
+ require 'psql-cm/cli'
102
+ ::PSQLCM::Console.run!
103
+ when "generate"
104
+ generate!
105
+ else
106
+ halt! "Action '#{action}' is not handled."
107
+ end
108
+ end
109
+
110
+ end # class << self
111
+ end
112
+
113
+ ::PSQLCM.config.debug = !!ENV['DEBUG']
114
+
@@ -0,0 +1,64 @@
1
+ require 'optparse'
2
+
3
+ module PSQLCM
4
+ class CLI
5
+
6
+ class << self
7
+ def parse!(arguments)
8
+ ::OptionParser.new do |options|
9
+ options.banner = "Usage: psql-cm [options]"
10
+ options.separator ""
11
+ options.separator "Specific options:"
12
+
13
+ options.on("-s", "--sql-path PATH", "Path to generate SQL cm files.") do |path|
14
+ ::PSQLCM.config.sql_path = path
15
+ end
16
+
17
+ options.on("-a", "--databases NAMES", "A comma separated list of databases to cm.") do |names|
18
+ ::PSQLCM.config.databases = names.split(',')
19
+ end
20
+
21
+ options.on("-u", "--uri URI", "Path to the sink database connection file.") do |uri|
22
+ ::PSQLCM.configure!(uri)
23
+ end
24
+
25
+ options.on("-D", "--[no-]debug", "Output debugging information.") do |debug|
26
+ ::PSQLCM.config.debug = debug.nil? ? false : true
27
+ end
28
+
29
+ options.on("-v", "--[no-]verbose", "Output verbosley.") do |verbose|
30
+ ::PSQLCM.config.verbose = verbose
31
+ end
32
+
33
+ options.on_tail("-h", "--help", "Print help and exit.") do
34
+ puts options
35
+ exit 0
36
+ end
37
+
38
+ options.on_tail("--version", "Print version and exit.") do
39
+ require 'psql-cm/version'
40
+ puts ::PSQLCM::Version
41
+ exit 0
42
+ end
43
+
44
+ options.parse!(arguments)
45
+
46
+ options
47
+ end # OptionParser.new
48
+ end # def self.parse
49
+
50
+ end # class << self
51
+ end # class CLI
52
+
53
+ class Console
54
+ class << self
55
+
56
+ def run!
57
+ require 'irb'
58
+ IRB.start
59
+ end
60
+
61
+ end # class << self
62
+ end # class Console
63
+ end # module PSQLCM
64
+
@@ -0,0 +1,41 @@
1
+ require 'uri'
2
+
3
+ module PSQLCM
4
+ # "postgres://{user}:{password}@{host}:{port}/{database}"
5
+ class << self
6
+ def db
7
+ return @db if @db
8
+ connect!
9
+ end
10
+
11
+ def connect!
12
+ @config.connection ||= {"dbname" => "postgres"}
13
+ @db = PG.connect(@config.connection)
14
+ end
15
+
16
+ def reconnect!
17
+ @db.close
18
+ connect!
19
+ end
20
+
21
+ def configure!(uri)
22
+ uri = URI.parse(::PSQLCM.config.uri)
23
+
24
+ query = uri.query.to_s.split('&')
25
+
26
+ timeout = query.detect { |k| k.match /connect_timeout=/ }.to_s.sub(/.*=/,'')
27
+ sslmode = query.detect { |k| k.match /sslmode=/ }.to_s.sub(/.*=/,'')
28
+
29
+ @config.connection = {
30
+ :host => uri.host,
31
+ :port => uri.port || 5432,
32
+ :dbname => "postgres", # uri.path.sub('/',''),
33
+ :user => uri.user,
34
+ :password => uri.password,
35
+ :connect_timeout => timeout.empty? ? 20 : timeout.to_i,
36
+ :sslmode => sslmode.empty? ? "disable" : sslmode # (disable|allow|prefer|require)
37
+ }.delete_if { |key, value| value.nil? }
38
+ end
39
+ end # class << self
40
+ end # module PSQLCM
41
+
@@ -0,0 +1,4 @@
1
+ module PSQLCM
2
+ Version = '0.0.1'
3
+ end
4
+
data/lib/psql-cm.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'pg'
2
+ require 'fileutils'
3
+
4
+ require_relative 'psql-cm/base'
5
+ require_relative 'psql-cm/database'
6
+
@@ -0,0 +1,6 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe PSQLCM do
4
+ before do
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+
4
+ require 'psql-cm'
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: psql-cm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wayne E. Seguin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pg
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: PostgreSQL Change Management Tool
31
+ email:
32
+ - wayneeseguin@gmail.com
33
+ executables:
34
+ - psql-cm
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - bin/psql-cm
39
+ - lib/psql-cm/base.rb
40
+ - lib/psql-cm/cli.rb
41
+ - lib/psql-cm/database.rb
42
+ - lib/psql-cm/version.rb
43
+ - lib/psql-cm.rb
44
+ - LICENCE
45
+ - README.md
46
+ - spec/psql-cm_spec.rb
47
+ - spec/spec_helper.rb
48
+ homepage: http://rubygems.org/gems/psql-cm/
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ version: 1.9.3
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: 1.8.22
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.22
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: PostgreSQL CM
72
+ test_files:
73
+ - spec/psql-cm_spec.rb
74
+ - spec/spec_helper.rb