dbgeni 0.10.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 +7 -0
- data/Rakefile +29 -0
- data/bin/dbgeni +2 -0
- data/lib/dbgeni/base.rb +146 -0
- data/lib/dbgeni/base_code.rb +143 -0
- data/lib/dbgeni/blank_slate.rb +24 -0
- data/lib/dbgeni/cli.rb +96 -0
- data/lib/dbgeni/code.rb +235 -0
- data/lib/dbgeni/code_list.rb +60 -0
- data/lib/dbgeni/commands/code.rb +151 -0
- data/lib/dbgeni/commands/commands.rb +41 -0
- data/lib/dbgeni/commands/config.rb +36 -0
- data/lib/dbgeni/commands/dmls.rb +244 -0
- data/lib/dbgeni/commands/generate.rb +257 -0
- data/lib/dbgeni/commands/initialize.rb +41 -0
- data/lib/dbgeni/commands/migrations.rb +243 -0
- data/lib/dbgeni/commands/milestones.rb +52 -0
- data/lib/dbgeni/commands/new.rb +178 -0
- data/lib/dbgeni/config.rb +325 -0
- data/lib/dbgeni/connectors/connector.rb +59 -0
- data/lib/dbgeni/connectors/mysql.rb +146 -0
- data/lib/dbgeni/connectors/oracle.rb +149 -0
- data/lib/dbgeni/connectors/sqlite.rb +166 -0
- data/lib/dbgeni/connectors/sybase.rb +97 -0
- data/lib/dbgeni/dml_cli.rb +35 -0
- data/lib/dbgeni/environment.rb +161 -0
- data/lib/dbgeni/exceptions/exception.rb +69 -0
- data/lib/dbgeni/file_converter.rb +44 -0
- data/lib/dbgeni/initializers/initializer.rb +44 -0
- data/lib/dbgeni/initializers/mysql.rb +36 -0
- data/lib/dbgeni/initializers/oracle.rb +38 -0
- data/lib/dbgeni/initializers/sqlite.rb +33 -0
- data/lib/dbgeni/initializers/sybase.rb +34 -0
- data/lib/dbgeni/logger.rb +60 -0
- data/lib/dbgeni/migration.rb +302 -0
- data/lib/dbgeni/migration_cli.rb +204 -0
- data/lib/dbgeni/migration_list.rb +91 -0
- data/lib/dbgeni/migrators/migrator.rb +40 -0
- data/lib/dbgeni/migrators/migrator_interface.rb +51 -0
- data/lib/dbgeni/migrators/mysql.rb +82 -0
- data/lib/dbgeni/migrators/oracle.rb +211 -0
- data/lib/dbgeni/migrators/sqlite.rb +90 -0
- data/lib/dbgeni/migrators/sybase.rb +118 -0
- data/lib/dbgeni/plugin.rb +92 -0
- data/lib/dbgeni.rb +52 -0
- metadata +87 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
module DBGeni
|
2
|
+
module Migrator
|
3
|
+
|
4
|
+
class Sqlite < DBGeni::Migrator::MigratorInterface
|
5
|
+
|
6
|
+
def initialize(config, connection)
|
7
|
+
super(config, connection)
|
8
|
+
end
|
9
|
+
|
10
|
+
def migration_errors
|
11
|
+
''
|
12
|
+
end
|
13
|
+
|
14
|
+
# def apply(migration, force=nil)
|
15
|
+
# end
|
16
|
+
|
17
|
+
# def rollback(migration, force=nil)
|
18
|
+
# end
|
19
|
+
|
20
|
+
# def verify(migration)
|
21
|
+
# end
|
22
|
+
|
23
|
+
def compile(code, force=false)
|
24
|
+
raise DBGeni::NotImplemented
|
25
|
+
end
|
26
|
+
|
27
|
+
# def remove(code)
|
28
|
+
# end
|
29
|
+
|
30
|
+
# def code_errors
|
31
|
+
# end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def run_in_client(file, force=nil)
|
36
|
+
null_device = '/dev/null'
|
37
|
+
if Kernel.is_windows?
|
38
|
+
null_device = 'NUL:'
|
39
|
+
end
|
40
|
+
|
41
|
+
@logfile = "#{@log_dir}/#{File.basename(file)}"
|
42
|
+
IO.popen("sqlite3 #{@connection.database} > #{@logfile} 2>&1", "w") do |p|
|
43
|
+
unless force
|
44
|
+
p.puts ".bail on"
|
45
|
+
end
|
46
|
+
p.puts ".echo on"
|
47
|
+
p.puts ".read #{file}"
|
48
|
+
p.puts ".quit"
|
49
|
+
end
|
50
|
+
# On OSX sqlite exits with 0 even when the sql script contains errors.
|
51
|
+
# On windows when there are errors it exits with 1.
|
52
|
+
#
|
53
|
+
# The only way to see if the script contained errors consistently is
|
54
|
+
# to grep the logfile for lines starting SQL error near line
|
55
|
+
# No point in checking if force is on as the errors don't matter anyway.
|
56
|
+
has_errors = false
|
57
|
+
unless force
|
58
|
+
# For empty migrations, sometimes no logfile?
|
59
|
+
if File.exists? @logfile
|
60
|
+
File.open(@logfile, 'r').each do |l|
|
61
|
+
if l =~ /^SQL error near line/
|
62
|
+
has_errors = true
|
63
|
+
break
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# When the system call ends, ruby sets $? with the exit status. A
|
69
|
+
# good exit status is 0 (zero) anything else means it went wrong
|
70
|
+
# If $? is anything but zero, raise an exception.
|
71
|
+
if $? != 0 or has_errors
|
72
|
+
# if there were errors in the migration, SQLITE seems to set a non-zero
|
73
|
+
# exit status on **windows only**, depite running the migration to completion.
|
74
|
+
# So if the exit status is non-zero AND force is NOT true, raise, otherwise don't.
|
75
|
+
unless force
|
76
|
+
raise DBGeni::MigrationContainsErrors
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def ensure_executable_exists
|
82
|
+
unless Kernel.executable_exists?('sqlite3')
|
83
|
+
raise DBGeni::DBCLINotOnPath
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module DBGeni
|
2
|
+
module Migrator
|
3
|
+
|
4
|
+
class Sybase < DBGeni::Migrator::MigratorInterface
|
5
|
+
|
6
|
+
def initialize(config, connection)
|
7
|
+
super(config, connection)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Defined in super ...
|
11
|
+
# def apply(migration, force=nil)
|
12
|
+
# end
|
13
|
+
|
14
|
+
# def rollback(migration, force=nil)
|
15
|
+
# end
|
16
|
+
|
17
|
+
def migration_errors
|
18
|
+
error = ''
|
19
|
+
# The first error is the one to report - with sybase isql doesn't stop on errors
|
20
|
+
# The error lines tend to look like:
|
21
|
+
# Msg 156, Level 15, State 2:
|
22
|
+
# Server 'WW637L18714A', Line 2:
|
23
|
+
# Incorrect syntax near the keyword 'table'.
|
24
|
+
begin
|
25
|
+
fh = File.open(@logfile, 'r')
|
26
|
+
# search for a line starting Msg or Error and then grab the next 2 lines to make up the error.
|
27
|
+
while (l = fh.readline)
|
28
|
+
if l =~ /^(Msg|Error)\s\d+/
|
29
|
+
error = l
|
30
|
+
break
|
31
|
+
end
|
32
|
+
end
|
33
|
+
unless error == ''
|
34
|
+
# if an error was found, add the next two lines to the error message
|
35
|
+
error << fh.readline
|
36
|
+
error << fh.readline
|
37
|
+
end
|
38
|
+
rescue ::EOFError
|
39
|
+
# reached the end of file before a full error message was found ...
|
40
|
+
# Just catch and move on ...
|
41
|
+
ensure
|
42
|
+
fh.close if fh
|
43
|
+
end
|
44
|
+
error
|
45
|
+
end
|
46
|
+
|
47
|
+
# def verify(migration)
|
48
|
+
# end
|
49
|
+
|
50
|
+
def remove(code, force=false)
|
51
|
+
begin
|
52
|
+
@connection.execute(drop_command(code))
|
53
|
+
rescue Exception => e
|
54
|
+
unless e.to_s =~ /Cannot drop the .*(procedure|function|trigger).+exist in the system catalogs/i
|
55
|
+
raise DBGeni::CodeRemoveFailed, e.to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def code_errors
|
61
|
+
# In sybase the code errors are just the same as migration errors
|
62
|
+
errors = migration_errors
|
63
|
+
if errors == ''
|
64
|
+
errors = nil
|
65
|
+
end
|
66
|
+
errors
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def run_in_client(file, force, is_proc=false)
|
72
|
+
@logfile = "#{@log_dir}/#{File.basename(file)}"
|
73
|
+
|
74
|
+
z = @config.env
|
75
|
+
# -e echos input
|
76
|
+
# -w200 - sets line width to 250 from the default of 80
|
77
|
+
response = system("isql -U#{z.username} -P#{z.password} -S#{z.sybase_service} -D#{z.database} -e -w 200 -i#{file} -o#{logfile}")
|
78
|
+
|
79
|
+
has_errors = false
|
80
|
+
unless force
|
81
|
+
# For empty migrations, sometimes no logfile?
|
82
|
+
if File.exists? @logfile
|
83
|
+
File.open(@logfile, 'r').each do |l|
|
84
|
+
if l =~ /^(Msg|Error)\s\d+/
|
85
|
+
has_errors = true
|
86
|
+
break
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if has_errors or !response
|
93
|
+
unless force
|
94
|
+
raise DBGeni::MigrationContainsErrors
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def ensure_executable_exists
|
100
|
+
unless Kernel.executable_exists?('isql')
|
101
|
+
raise DBGeni::DBCLINotOnPath
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def drop_command(code)
|
106
|
+
case code.type
|
107
|
+
when DBGeni::Code::TRIGGER
|
108
|
+
"drop trigger #{code.name.downcase}"
|
109
|
+
when DBGeni::Code::FUNCTION
|
110
|
+
"drop function #{code.name.downcase}"
|
111
|
+
when DBGeni::Code::PROCEDURE
|
112
|
+
"drop procedure #{code.name.downcase}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module DBGeni
|
2
|
+
class Plugin
|
3
|
+
class << self
|
4
|
+
attr_reader :hooks
|
5
|
+
|
6
|
+
def install_plugin(hook, klass)
|
7
|
+
unless @hooks.has_key? hook
|
8
|
+
raise DBGeni::InvalidHook
|
9
|
+
end
|
10
|
+
@hooks[hook].push klass
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset
|
14
|
+
@hooks.keys.each do |k|
|
15
|
+
@hooks[k] = Array.new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
@hooks = {
|
22
|
+
:before_migration_up => [],
|
23
|
+
:after_migration_up => [],
|
24
|
+
:before_migration_down => [],
|
25
|
+
:after_migration_down => [],
|
26
|
+
:before_dml_up => [],
|
27
|
+
:after_dml_up => [],
|
28
|
+
:before_dml_down => [],
|
29
|
+
:after_dml_down => [],
|
30
|
+
:before_code_apply => [],
|
31
|
+
:after_code_apply => [],
|
32
|
+
:before_code_remove => [],
|
33
|
+
:after_code_remove => [],
|
34
|
+
:before_running_migrations => [],
|
35
|
+
:after_running_migrations => [],
|
36
|
+
:before_running_dmls => [],
|
37
|
+
:after_running_dmls => [],
|
38
|
+
:before_modifying_code => [],
|
39
|
+
:after_modifying_code => []
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
def initialize
|
44
|
+
end
|
45
|
+
|
46
|
+
def load_plugins(path)
|
47
|
+
begin
|
48
|
+
files = Dir.entries(path).grep(/\.rb$/).sort
|
49
|
+
rescue Errno::ENOENT, Errno::EACCES => e
|
50
|
+
raise DBGeni::PluginDirectoryNotAccessible, e.to_s
|
51
|
+
end
|
52
|
+
files.each do |f|
|
53
|
+
load_plugin File.join(path, f)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_plugin(filename)
|
58
|
+
require filename
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_plugins(hook, attrs)
|
62
|
+
klasses = self.class.hooks[hook]
|
63
|
+
unless klasses.is_a? Array
|
64
|
+
raise DBGeni::InvalidHook, hook
|
65
|
+
end
|
66
|
+
|
67
|
+
klasses.each do |k|
|
68
|
+
run_plugin k, hook, attrs
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def run_plugin(klass, hook, attrs)
|
73
|
+
instance = klass.new
|
74
|
+
unless instance.respond_to? :run
|
75
|
+
raise DBGeni::PluginDoesNotRespondToRun
|
76
|
+
end
|
77
|
+
instance.run(hook, attrs)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Class
|
84
|
+
DBGeni::Plugin.hooks.keys.each do |k|
|
85
|
+
self.class_eval <<-end_eval
|
86
|
+
def #{k.to_s}
|
87
|
+
DBGeni::Plugin.install_plugin(:#{k.to_s}, self)
|
88
|
+
end
|
89
|
+
end_eval
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
data/lib/dbgeni.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
|
6
|
+
def self.is_windows?
|
7
|
+
# Ruby 1.9.3 warns if you use Config (instead of RbConfig) while older Ruby
|
8
|
+
# doesn't have RbConfig, only Config :-/
|
9
|
+
conf = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
|
10
|
+
conf['host_os'] =~ /mswin|mingw/
|
11
|
+
end
|
12
|
+
|
13
|
+
def suppress_warnings
|
14
|
+
original_verbosity = $VERBOSE
|
15
|
+
$VERBOSE = nil
|
16
|
+
result = yield
|
17
|
+
$VERBOSE = original_verbosity
|
18
|
+
return result
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.executable_exists?(cmd)
|
22
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
23
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
24
|
+
exts.each { |ext|
|
25
|
+
exe = "#{path}/#{cmd}#{ext}"
|
26
|
+
return exe if File.executable? exe
|
27
|
+
}
|
28
|
+
end
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
if RUBY_PLATFORM == 'java'
|
35
|
+
require 'rubygems'
|
36
|
+
require 'java'
|
37
|
+
|
38
|
+
conf = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
|
39
|
+
if conf['ruby_version'] =~ /1\.8/
|
40
|
+
raise "DBGeni requires the --1.9 switch to be passed to jruby (or set env variable JRUBY_OPTS=--1.9)"
|
41
|
+
end
|
42
|
+
|
43
|
+
module JavaLang
|
44
|
+
include_package "java.lang"
|
45
|
+
end
|
46
|
+
|
47
|
+
module JavaSql
|
48
|
+
include_package 'java.sql'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
require 'dbgeni/base'
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dbgeni
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen O'Donnell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-11 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Generic installer to manage database migrations for various databases
|
14
|
+
email: stephen@betteratoracle.com
|
15
|
+
executables:
|
16
|
+
- dbgeni
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- Rakefile
|
21
|
+
- bin/dbgeni
|
22
|
+
- lib/dbgeni.rb
|
23
|
+
- lib/dbgeni/base.rb
|
24
|
+
- lib/dbgeni/base_code.rb
|
25
|
+
- lib/dbgeni/blank_slate.rb
|
26
|
+
- lib/dbgeni/cli.rb
|
27
|
+
- lib/dbgeni/code.rb
|
28
|
+
- lib/dbgeni/code_list.rb
|
29
|
+
- lib/dbgeni/commands/code.rb
|
30
|
+
- lib/dbgeni/commands/commands.rb
|
31
|
+
- lib/dbgeni/commands/config.rb
|
32
|
+
- lib/dbgeni/commands/dmls.rb
|
33
|
+
- lib/dbgeni/commands/generate.rb
|
34
|
+
- lib/dbgeni/commands/initialize.rb
|
35
|
+
- lib/dbgeni/commands/migrations.rb
|
36
|
+
- lib/dbgeni/commands/milestones.rb
|
37
|
+
- lib/dbgeni/commands/new.rb
|
38
|
+
- lib/dbgeni/config.rb
|
39
|
+
- lib/dbgeni/connectors/connector.rb
|
40
|
+
- lib/dbgeni/connectors/mysql.rb
|
41
|
+
- lib/dbgeni/connectors/oracle.rb
|
42
|
+
- lib/dbgeni/connectors/sqlite.rb
|
43
|
+
- lib/dbgeni/connectors/sybase.rb
|
44
|
+
- lib/dbgeni/dml_cli.rb
|
45
|
+
- lib/dbgeni/environment.rb
|
46
|
+
- lib/dbgeni/exceptions/exception.rb
|
47
|
+
- lib/dbgeni/file_converter.rb
|
48
|
+
- lib/dbgeni/initializers/initializer.rb
|
49
|
+
- lib/dbgeni/initializers/mysql.rb
|
50
|
+
- lib/dbgeni/initializers/oracle.rb
|
51
|
+
- lib/dbgeni/initializers/sqlite.rb
|
52
|
+
- lib/dbgeni/initializers/sybase.rb
|
53
|
+
- lib/dbgeni/logger.rb
|
54
|
+
- lib/dbgeni/migration.rb
|
55
|
+
- lib/dbgeni/migration_cli.rb
|
56
|
+
- lib/dbgeni/migration_list.rb
|
57
|
+
- lib/dbgeni/migrators/migrator.rb
|
58
|
+
- lib/dbgeni/migrators/migrator_interface.rb
|
59
|
+
- lib/dbgeni/migrators/mysql.rb
|
60
|
+
- lib/dbgeni/migrators/oracle.rb
|
61
|
+
- lib/dbgeni/migrators/sqlite.rb
|
62
|
+
- lib/dbgeni/migrators/sybase.rb
|
63
|
+
- lib/dbgeni/plugin.rb
|
64
|
+
homepage: http://dbgeni.com
|
65
|
+
licenses: []
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 2.2.0
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: A generic database installer
|
87
|
+
test_files: []
|