dbgeni 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|