dbsketch 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.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +1 -0
- data/lib/dbsketch.rb +64 -0
- data/lib/dbsketch/automation/automation_error.rb +15 -0
- data/lib/dbsketch/automation/database_connection_details.rb +32 -0
- data/lib/dbsketch/automation/database_importer.rb +184 -0
- data/lib/dbsketch/automation/database_proxy.rb +78 -0
- data/lib/dbsketch/automation/table_importer.rb +114 -0
- data/lib/dbsketch/comparison/check_constraint_comparator.rb +54 -0
- data/lib/dbsketch/comparison/column_comparator.rb +65 -0
- data/lib/dbsketch/comparison/comparison_error.rb +15 -0
- data/lib/dbsketch/comparison/computed_column_comparator.rb +63 -0
- data/lib/dbsketch/comparison/database_comparator.rb +115 -0
- data/lib/dbsketch/comparison/diff.rb +37 -0
- data/lib/dbsketch/comparison/foreign_key_comparator.rb +56 -0
- data/lib/dbsketch/comparison/function_comparator.rb +56 -0
- data/lib/dbsketch/comparison/index_comparator.rb +65 -0
- data/lib/dbsketch/comparison/primary_key_comparator.rb +61 -0
- data/lib/dbsketch/comparison/procedure_comparator.rb +54 -0
- data/lib/dbsketch/comparison/table_comparator.rb +158 -0
- data/lib/dbsketch/comparison/trigger_comparator.rb +53 -0
- data/lib/dbsketch/comparison/type_comparator.rb +51 -0
- data/lib/dbsketch/comparison/unique_constraint_comparator.rb +58 -0
- data/lib/dbsketch/comparison/view_comparator.rb +54 -0
- data/lib/dbsketch/model/abstract_column.rb +25 -0
- data/lib/dbsketch/model/check_constraint.rb +23 -0
- data/lib/dbsketch/model/column.rb +35 -0
- data/lib/dbsketch/model/computed_column.rb +27 -0
- data/lib/dbsketch/model/custom_code.rb +21 -0
- data/lib/dbsketch/model/database.rb +87 -0
- data/lib/dbsketch/model/database_object.rb +71 -0
- data/lib/dbsketch/model/foreign_key.rb +29 -0
- data/lib/dbsketch/model/function.rb +23 -0
- data/lib/dbsketch/model/index.rb +40 -0
- data/lib/dbsketch/model/model_error.rb +15 -0
- data/lib/dbsketch/model/operation.rb +28 -0
- data/lib/dbsketch/model/primary_key.rb +33 -0
- data/lib/dbsketch/model/procedure.rb +18 -0
- data/lib/dbsketch/model/table.rb +171 -0
- data/lib/dbsketch/model/trigger.rb +32 -0
- data/lib/dbsketch/model/type.rb +92 -0
- data/lib/dbsketch/model/unique_constraint.rb +33 -0
- data/lib/dbsketch/model/view.rb +23 -0
- data/lib/dbsketch/rendering/meta/column_renderer.rb +76 -0
- data/lib/dbsketch/rendering/meta/database_renderer.rb +112 -0
- data/lib/dbsketch/rendering/meta/foreign_key_renderer.rb +31 -0
- data/lib/dbsketch/rendering/meta/index_renderer.rb +30 -0
- data/lib/dbsketch/rendering/meta/operation_renderer.rb +66 -0
- data/lib/dbsketch/rendering/meta/table_renderer.rb +177 -0
- data/lib/dbsketch/rendering/meta/trigger_renderer.rb +31 -0
- data/lib/dbsketch/rendering/meta/type_renderer.rb +37 -0
- data/lib/dbsketch/rendering/meta/view_renderer.rb +32 -0
- data/lib/dbsketch/rendering/sql/column_renderer.rb +75 -0
- data/lib/dbsketch/rendering/sql/database_diff_renderer.rb +94 -0
- data/lib/dbsketch/rendering/sql/database_renderer.rb +139 -0
- data/lib/dbsketch/rendering/sql/foreign_key_renderer.rb +24 -0
- data/lib/dbsketch/rendering/sql/index_renderer.rb +31 -0
- data/lib/dbsketch/rendering/sql/operation_renderer.rb +64 -0
- data/lib/dbsketch/rendering/sql/table_renderer.rb +148 -0
- data/lib/dbsketch/rendering/sql/trigger_renderer.rb +31 -0
- data/lib/dbsketch/rendering/sql/type_renderer.rb +28 -0
- data/lib/dbsketch/rendering/sql/view_renderer.rb +31 -0
- data/lib/dbsketch/version.rb +3 -0
- metadata +134 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Unique constraint
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'column'
|
6
|
+
require_relative 'database_object'
|
7
|
+
|
8
|
+
module Dbsketch
|
9
|
+
module Model
|
10
|
+
|
11
|
+
class UniqueConstraint < Database_Object
|
12
|
+
def initialize name, columns, meaning: nil, comment: nil
|
13
|
+
super name, :meaning => meaning, :comment => comment
|
14
|
+
@columns = columns.is_a?(Array) ? columns : [columns]
|
15
|
+
### Preconditions
|
16
|
+
@columns.each_with_index do |column, index|
|
17
|
+
raise ArgumentError, "columns[#{index}] is not a Dbsketch::Model::Column" unless column.is_a? Column
|
18
|
+
end
|
19
|
+
###
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :columns
|
23
|
+
|
24
|
+
def has_column? column_name
|
25
|
+
### Preconditions
|
26
|
+
raise ArgumentError, "column_name is not a String" unless column_name.is_a? String
|
27
|
+
###
|
28
|
+
nil != @columns.find { |c| c.name.downcase == column_name.downcase }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Defines database view
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'database_object'
|
6
|
+
|
7
|
+
module Dbsketch
|
8
|
+
module Model
|
9
|
+
|
10
|
+
class View < Database_Object
|
11
|
+
def initialize name, query, meaning: nil, comment: nil, dependencies: []
|
12
|
+
super name, :meaning => meaning, :comment => comment, :dependencies => dependencies
|
13
|
+
### Preconditions
|
14
|
+
raise ArgumentError, "query is not a String" unless query.is_a? String
|
15
|
+
###
|
16
|
+
@query = query
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :query
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Render a column into SQL
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative '../../model/abstract_column'
|
6
|
+
require_relative '../../model/column'
|
7
|
+
require_relative '../../model/computed_column'
|
8
|
+
|
9
|
+
require_relative 'type_renderer'
|
10
|
+
|
11
|
+
module Dbsketch
|
12
|
+
module Rendering
|
13
|
+
module Meta
|
14
|
+
|
15
|
+
class ColumnRenderer
|
16
|
+
def initialize type_renderer: nil, keywords: {}
|
17
|
+
### Preconditions
|
18
|
+
raise ArgumentError, "keywords is not a Hash" unless keywords.is_a? Hash
|
19
|
+
###
|
20
|
+
@keywords = {
|
21
|
+
:column => "Dbsketch::Model::Column.new",
|
22
|
+
:computed_column => "Dbsketch::Model::ComputedColumn.new",
|
23
|
+
:type => "Dbsketch::Model::Type.new"
|
24
|
+
}.merge keywords
|
25
|
+
@type_renderer = (nil == type_renderer ? TypeRenderer.new(:type_keyword => @keywords[:type]) : type_renderer)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create column
|
29
|
+
### Preconditions
|
30
|
+
raise ArgumentError, "column is not a Dbsketch::Model::AbstractColumn" unless column.is_a? Dbsketch::Model::AbstractColumn
|
31
|
+
###
|
32
|
+
if column.is_a? Dbsketch::Model::ComputedColumn
|
33
|
+
create_computed_column column
|
34
|
+
elsif column.is_a? Dbsketch::Model::Column
|
35
|
+
create_column column
|
36
|
+
else
|
37
|
+
raise ArgumentError, "#{column.class} is an unknown subclass of Dbsketch::Model::AbstractColumn"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def get_semantic column
|
44
|
+
str = ""
|
45
|
+
str << ", :meaning => '#{column.meaning}'" if column.meaning
|
46
|
+
str << ", :comment => '#{column.comment}'" if column.comment
|
47
|
+
str
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_column column
|
51
|
+
str = "#{@keywords[:column]}('#{column.name}', #{@type_renderer.create column.type}"
|
52
|
+
str << ", :order => #{column.order}" if nil != column.order
|
53
|
+
str << ", :identity => true" if column.identity
|
54
|
+
str << ", :nullable => false" if not column.nullable
|
55
|
+
if nil != column.default
|
56
|
+
str << ", :default => #{column.default.is_a?(String) ? "'#{column.default}'" : column.default}"
|
57
|
+
end
|
58
|
+
str << get_semantic(column)
|
59
|
+
str << ")"
|
60
|
+
str
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_computed_column column
|
64
|
+
str = "#{@keywords[:computed_column]}('#{column.name}', '#{column.query}'"
|
65
|
+
str << ", :nullable => false" if not column.nullable
|
66
|
+
str << ", :persisted => true" if column.persisted
|
67
|
+
str << get_semantic(column)
|
68
|
+
str << ")"
|
69
|
+
str
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Render a database into ruby
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative '../../comparison/database_comparator'
|
6
|
+
require_relative '../../model/database'
|
7
|
+
|
8
|
+
require_relative 'index_renderer'
|
9
|
+
require_relative 'operation_renderer'
|
10
|
+
require_relative 'table_renderer'
|
11
|
+
require_relative 'trigger_renderer'
|
12
|
+
require_relative 'view_renderer'
|
13
|
+
|
14
|
+
module Dbsketch
|
15
|
+
module Rendering
|
16
|
+
module Meta
|
17
|
+
|
18
|
+
class DatabaseRenderer
|
19
|
+
def initialize index_renderer: nil, operation_renderer: nil, table_renderer: nil, trigger_renderer: nil, view_renderer: nil, options: {}, keywords: {}
|
20
|
+
### Preconditions
|
21
|
+
raise ArgumentError, "index_renderer is not a Dbsketch::Rendering::Meta::IndexRenderer" unless nil == index_renderer or index_renderer.is_a? IndexRenderer
|
22
|
+
raise ArgumentError, "operation_renderer is not a Dbsketch::Rendering::Meta::OperationRenderer" unless nil == operation_renderer or operation_renderer.is_a? OperationRenderer
|
23
|
+
raise ArgumentError, "table_renderer is not a Dbsketch::Rendering::Meta::TableRenderer" unless nil == table_renderer or table_renderer.is_a? TableRenderer
|
24
|
+
raise ArgumentError, "trigger_renderer is not a Dbsketch::Rendering::Meta::TriggerRenderer" unless nil == trigger_renderer or trigger_renderer.is_a? TriggerRenderer
|
25
|
+
raise ArgumentError, "view_renderer is not a Dbsketch::Rendering::Meta::ViewRenderer" unless nil == view_renderer or view_renderer.is_a? ViewRenderer
|
26
|
+
raise ArgumentError, "options is not a Hash" unless options.is_a? Hash
|
27
|
+
raise ArgumentError, "keywords is not a Hash" unless keywords.is_a? Hash
|
28
|
+
###
|
29
|
+
@options = {
|
30
|
+
:order_by_dependencies => true,
|
31
|
+
:pretty => false
|
32
|
+
}.merge options
|
33
|
+
@keywords = keywords
|
34
|
+
@index_renderer = (nil == index_renderer ? IndexRenderer.new : index_renderer)
|
35
|
+
@operation_renderer = (nil == operation_renderer ? OperationRenderer.new : operation_renderer)
|
36
|
+
@table_renderer = (nil == table_renderer ? TableRenderer.new(:options => @options, :keywords => @keywords) : table_renderer)
|
37
|
+
@trigger_renderer = (nil == trigger_renderer ? TriggerRenderer.new : trigger_renderer)
|
38
|
+
@view_renderer = (nil == view_renderer ? ViewRenderer.new : view_renderer)
|
39
|
+
end
|
40
|
+
|
41
|
+
def create database
|
42
|
+
### Preconditions
|
43
|
+
raise ArgumentError, "database is not a Dbsketch::Model::Database" unless database.is_a? Dbsketch::Model::Database
|
44
|
+
###
|
45
|
+
separator = @options[:pretty] ? "\n\n" : "\n"
|
46
|
+
database.order_items! if @options[:order_by_dependencies]
|
47
|
+
database.items.map { |i| create_item i }.flatten.compact.join(separator) + separator
|
48
|
+
end
|
49
|
+
|
50
|
+
def alter database_diff
|
51
|
+
### Preconditions
|
52
|
+
raise ArgumentError, "database_diff is not a Dbsketch::Comparison::DatabaseDiff" unless database_diff.is_a? Dbsketch::Comparison::DatabaseDiff
|
53
|
+
###
|
54
|
+
separator = "\n"
|
55
|
+
|
56
|
+
diffs = database_diff.indexes + database_diff.operations + database_diff.tables + database_diff.triggers + database_diff.views
|
57
|
+
deletions = diffs.select { |d| d.deletion? }.map { |i| drop_item i.old_value }
|
58
|
+
changes = diffs.select { |d| d.change? }.map { |i| alter_item(i) }
|
59
|
+
creations = diffs.select { |d| d.addition? }.map { |i| create_item i.new_value }
|
60
|
+
|
61
|
+
(deletions + changes + creations).flatten.compact.join(separator) + separator
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def create_item item
|
67
|
+
if item.is_a? Dbsketch::Model::Index
|
68
|
+
@index_renderer.create item
|
69
|
+
elsif item.is_a? Dbsketch::Model::Operation
|
70
|
+
@operation_renderer.create item
|
71
|
+
elsif item.is_a? Dbsketch::Model::Table
|
72
|
+
@table_renderer.create item
|
73
|
+
elsif item.is_a? Dbsketch::Model::Trigger
|
74
|
+
@trigger_renderer.create item
|
75
|
+
elsif item.is_a? Dbsketch::Model::View
|
76
|
+
@view_renderer.create item
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def drop_item item
|
81
|
+
if item.is_a? Dbsketch::Model::Index
|
82
|
+
@index_renderer.drop item
|
83
|
+
elsif item.is_a? Dbsketch::Model::Operation
|
84
|
+
@operation_renderer.drop item
|
85
|
+
elsif item.is_a? Dbsketch::Model::Table
|
86
|
+
@table_renderer.drop item
|
87
|
+
elsif item.is_a? Dbsketch::Model::Trigger
|
88
|
+
@trigger_renderer.drop item
|
89
|
+
elsif item.is_a? Dbsketch::Model::View
|
90
|
+
@view_renderer.drop item
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def alter_item item_diff
|
95
|
+
if item_diff.old_value.is_a? Dbsketch::Model::Index
|
96
|
+
"Index.alter #{create_item(item_diff.new_value)}"
|
97
|
+
elsif item_diff.old_value.is_a? Dbsketch::Model::Operation
|
98
|
+
"Operation.alter #{create_item(item_diff.new_value)}"
|
99
|
+
elsif item_diff.old_value.is_a? Dbsketch::Model::Table
|
100
|
+
@table_renderer.alter item_diff
|
101
|
+
elsif item_diff.old_value.is_a? Dbsketch::Model::Trigger
|
102
|
+
"Trigger.alter #{create_item(item_diff.new_value)}"
|
103
|
+
elsif item_diff.old_value.is_a? Dbsketch::Model::View
|
104
|
+
"View.alter #{create_item(item_diff.new_value)}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Render a column into ruby
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative '../../model/foreign_key'
|
6
|
+
|
7
|
+
module Dbsketch
|
8
|
+
module Rendering
|
9
|
+
module Meta
|
10
|
+
|
11
|
+
class ForeignKeyRenderer
|
12
|
+
|
13
|
+
def initialize foreign_key_keyword: "Dbsketch::Model::ForeignKey.new"
|
14
|
+
### Preconditions
|
15
|
+
raise ArgumentError, "foreign_key_keyword is not a String" unless foreign_key_keyword.is_a? String
|
16
|
+
###
|
17
|
+
@foreign_key_keyword = foreign_key_keyword
|
18
|
+
end
|
19
|
+
|
20
|
+
def create foreign_key
|
21
|
+
### Preconditions
|
22
|
+
raise ArgumentError, "foreign_key is not a Dbsketch::Model::ForeignKey" unless foreign_key.is_a? Dbsketch::Model::ForeignKey
|
23
|
+
###
|
24
|
+
"#{@foreign_key_keyword}(\"#{foreign_key.name}\", #{foreign_key.constricted_column.name}, #{foreign_key.referenced_table.name}, #{foreign_key.referenced_table.name}['#{foreign_key.referenced_column.name}'])"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Render an index into ruby
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative '../../model/index'
|
6
|
+
|
7
|
+
module Dbsketch
|
8
|
+
module Rendering
|
9
|
+
module Meta
|
10
|
+
|
11
|
+
class IndexRenderer
|
12
|
+
|
13
|
+
def create index
|
14
|
+
### Preconditions
|
15
|
+
raise ArgumentError, "index is not a Dbsketch::Model::Index" unless index.is_a? Dbsketch::Model::Index
|
16
|
+
###
|
17
|
+
columns = index.columns.map {|c| c.name }
|
18
|
+
columns = columns.count > 1 ? "[#{columns.join(", ")}]" : columns.first
|
19
|
+
"Dbsketch::Model::Index.new(\"#{index.name}\", #{index.target.name}, #{columns})"
|
20
|
+
end
|
21
|
+
|
22
|
+
def drop index
|
23
|
+
"Index.drop #{index.name} from #{index.target.name}"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Render a column into ruby
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative '../../model/function'
|
6
|
+
require_relative '../../model/procedure'
|
7
|
+
|
8
|
+
module Dbsketch
|
9
|
+
module Rendering
|
10
|
+
module Meta
|
11
|
+
|
12
|
+
class OperationRenderer
|
13
|
+
|
14
|
+
def create operation
|
15
|
+
### Preconditions
|
16
|
+
raise ArgumentError, "operation is not a Dbsketch::Model::Operation" unless operation.is_a? Dbsketch::Model::Operation
|
17
|
+
###
|
18
|
+
if operation.is_a? Dbsketch::Model::Function
|
19
|
+
create_function operation
|
20
|
+
elsif operation.is_a? Dbsketch::Model::Procedure
|
21
|
+
create_procedure operation
|
22
|
+
else
|
23
|
+
raise ArgumentError, "#{operation.class} is an unknown subclass of Dbsketch::Model::Operation"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def drop operation
|
28
|
+
### Preconditions
|
29
|
+
raise ArgumentError, "operation is not a Dbsketch::Model::Operation" unless operation.is_a? Dbsketch::Model::Operation
|
30
|
+
###
|
31
|
+
if operation.is_a? Dbsketch::Model::Function
|
32
|
+
keyword = "Function"
|
33
|
+
elsif operation.is_a? Dbsketch::Model::Procedure
|
34
|
+
keyword = "Procedure"
|
35
|
+
else
|
36
|
+
raise ArgumentError, "#{operation.class} is an unknown subclass of Dbsketch::Model::Operation"
|
37
|
+
end
|
38
|
+
"#{keyword}.drop #{operation.name}"
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def create_function function
|
44
|
+
arguments = function.arguments.map {|a| "\"#{a}\"" }
|
45
|
+
arguments = function.arguments.count > 1 ? "[#{arguments.join(", ")}]" : arguments.first
|
46
|
+
sql = "Dbsketch::Model::Function.new(\"#{function.name}\""
|
47
|
+
sql << ", :arguments => #{arguments}" if nil != arguments
|
48
|
+
sql << ", :returns => \"#{function.returns}\""
|
49
|
+
sql << ", :algo => \"#{function.algo}\")"
|
50
|
+
sql
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_procedure procedure
|
54
|
+
arguments = procedure.arguments.map {|a| "\"#{a}\"" }
|
55
|
+
arguments = procedure.arguments.count > 1 ? "[#{arguments.join(", ")}]" : arguments.first
|
56
|
+
sql = "Dbsketch::Model::Procedure.new(\"#{procedure.name}\""
|
57
|
+
sql << ", :arguments => #{arguments}" if nil != arguments
|
58
|
+
sql << ", :algo => \"#{procedure.algo}\")"
|
59
|
+
sql
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Render a table into Ruby
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative '../../comparison/table_comparator'
|
6
|
+
require_relative '../../model/table'
|
7
|
+
|
8
|
+
require_relative 'column_renderer'
|
9
|
+
require_relative 'foreign_key_renderer'
|
10
|
+
|
11
|
+
module Dbsketch
|
12
|
+
module Rendering
|
13
|
+
module Meta
|
14
|
+
|
15
|
+
class TableRenderer
|
16
|
+
def initialize column_renderer: nil, fk_renderer: nil, options: {}, keywords: {}
|
17
|
+
### Preconditions
|
18
|
+
raise ArgumentError, "options is not a Hash" unless options.is_a? Hash
|
19
|
+
raise ArgumentError, "keywords is not a Hash" unless keywords.is_a? Hash
|
20
|
+
###
|
21
|
+
@options = {
|
22
|
+
:pretty => false,
|
23
|
+
}.merge options
|
24
|
+
@keywords = {
|
25
|
+
:check_constraint => "Dbsketch::Model::CheckConstraint.new",
|
26
|
+
:primary_key => "Dbsketch::Model::PrimaryKey.new",
|
27
|
+
:foreign_key => "Dbsketch::Model::ForeignKey.new",
|
28
|
+
:table => "Dbsketch::Model::Table.new",
|
29
|
+
:unique_constraint => "Dbsketch::Model::UniqueConstraint.new"
|
30
|
+
}.merge keywords
|
31
|
+
@column_renderer = (nil == column_renderer ? ColumnRenderer.new(:keywords => @keywords) : column_renderer)
|
32
|
+
@fk_renderer = (nil == fk_renderer ? ForeignKeyRenderer.new(:foreign_key_keyword => @keywords[:foreign_key] ) : fk_renderer)
|
33
|
+
end
|
34
|
+
|
35
|
+
def create table
|
36
|
+
### Preconditions
|
37
|
+
raise ArgumentError, "table is not a Dbsketch::Model::Table" unless table.is_a? Dbsketch::Model::Table
|
38
|
+
###
|
39
|
+
columns = collect_columns table
|
40
|
+
str = "#{@keywords[:table]}(\"#{table.name}\""
|
41
|
+
str << ", :meaning => \"#{table.meaning}\"" if nil != table.meaning
|
42
|
+
str << ", :comment => \"#{table.comment}\"" if nil != table.comment
|
43
|
+
str << ", #{columns}" if not columns.empty?
|
44
|
+
str << ")"
|
45
|
+
constraints = collect_constraints table
|
46
|
+
str << "\n#{constraints.join("\n")}" if not constraints.empty?
|
47
|
+
str
|
48
|
+
end
|
49
|
+
|
50
|
+
def drop table
|
51
|
+
### Preconditions
|
52
|
+
raise ArgumentError, "table is not a Dbsketch::Model::Table" unless table.is_a? Dbsketch::Model::Table
|
53
|
+
###
|
54
|
+
"Table.drop #{table.name}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def alter table_diff
|
58
|
+
### Preconditions
|
59
|
+
raise ArgumentError, "table_diff is not a Dbsketch::Comparison::TableDiff" unless table_diff.is_a? Dbsketch::Comparison::TableDiff
|
60
|
+
###
|
61
|
+
queries = []
|
62
|
+
|
63
|
+
# Columns
|
64
|
+
deleted_columns = table_diff.columns.select { |d| d.deletion? }
|
65
|
+
if not deleted_columns.empty?
|
66
|
+
queries << "Table.alter #{table_diff.new_table.name} drop column\n\t#{deleted_columns.map { |d| d.old_column.name }.join("\n\t")}"
|
67
|
+
end
|
68
|
+
added_columns = table_diff.columns.select { |d| d.addition? }
|
69
|
+
if not added_columns.empty?
|
70
|
+
queries << "Table.alter #{table_diff.new_table.name} add column\n\t#{added_columns.map { |d| @column_renderer.create d.new_column }.join("\n\t")}"
|
71
|
+
end
|
72
|
+
changed_columns = table_diff.columns.select { |d| d.change? }
|
73
|
+
if not changed_columns.empty?
|
74
|
+
queries << "Table.alter #{table_diff.new_table.name} alter column\n\t#{changed_columns.map { |d| @column_renderer.create d.new_column }.join("\n\t")}"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Primary key
|
78
|
+
if nil != table_diff.primary_key
|
79
|
+
queries << "Table.alter #{table_diff.new_table.name} drop primary key #{table_diff.primary_key.old_key.name}" if table_diff.primary_key.deletion?
|
80
|
+
queries << "Table.alter #{table_diff.new_table.name} alter #{create_primary_key table_diff.new_table, table_diff.primary_key.new_key}" if table_diff.primary_key.change?
|
81
|
+
queries << "Table.alter #{table_diff.new_table.name} add #{create_primary_key table_diff.new_table, table_diff.primary_key.new_key}" if table_diff.primary_key.addition?
|
82
|
+
end
|
83
|
+
|
84
|
+
# Check constraints
|
85
|
+
deleted = table_diff.check_constraints.select { |d| d.deletion? }
|
86
|
+
if not deleted.empty?
|
87
|
+
queries << "Table.alter #{table_diff.new_table.name} drop check constraint\n\t#{deleted.map { |d| d.old_constraint.name }.join("\n\t")}"
|
88
|
+
end
|
89
|
+
added = table_diff.check_constraints.select { |d| d.addition? }
|
90
|
+
if not added.empty?
|
91
|
+
queries << "Table.alter #{table_diff.new_table.name} add\n\t#{added.map { |d| create_check_constraint d.new_constraint }.join("\n\t")}"
|
92
|
+
end
|
93
|
+
changed = table_diff.check_constraints.select { |d| d.change? }
|
94
|
+
if not changed.empty?
|
95
|
+
queries << "Table.alter #{table_diff.new_table.name} alter\n\t#{changed.map { |d| create_check_constraint d.new_constraint }.join("\n\t")}"
|
96
|
+
end
|
97
|
+
queries.flatten.join("\n")
|
98
|
+
|
99
|
+
# Foreign keys
|
100
|
+
deleted = table_diff.foreign_keys.select { |d| d.deletion? }
|
101
|
+
if not deleted.empty?
|
102
|
+
queries << "Table.alter #{table_diff.new_table.name} drop foreign key\n\t#{deleted.map { |d| d.old_key.name }.join("\n\t")}"
|
103
|
+
end
|
104
|
+
added = table_diff.foreign_keys.select { |d| d.addition? }
|
105
|
+
if not added.empty?
|
106
|
+
queries << "Table.alter #{table_diff.new_table.name} add\n\t#{added.map { |d| @fk_renderer.create d.new_key }.join("\n\t")}"
|
107
|
+
end
|
108
|
+
changed = table_diff.foreign_keys.select { |d| d.change? }
|
109
|
+
if not changed.empty?
|
110
|
+
queries << "Table.alter #{table_diff.new_table.name} alter\n\t#{changed.map { |d| @fk_renderer.create d.new_key }.join("\n\t")}"
|
111
|
+
end
|
112
|
+
queries.flatten.join("\n")
|
113
|
+
|
114
|
+
# Unique constraints
|
115
|
+
deleted = table_diff.unique_constraints.select { |d| d.deletion? }
|
116
|
+
if not deleted.empty?
|
117
|
+
queries << "Table.alter #{table_diff.new_table.name} drop unique constraint\n\t#{deleted.map { |d| d.old_constraint.name }.join("\n\t")}"
|
118
|
+
end
|
119
|
+
added = table_diff.unique_constraints.select { |d| d.addition? }
|
120
|
+
if not added.empty?
|
121
|
+
queries << "Table.alter #{table_diff.new_table.name} add\n\t#{added.map { |d| create_unique_constraint d.new_constraint, table_diff.new_table }.join("\n\t")}"
|
122
|
+
end
|
123
|
+
changed = table_diff.unique_constraints.select { |d| d.change? }
|
124
|
+
if not changed.empty?
|
125
|
+
queries << "Table.alter #{table_diff.new_table.name} alter\n\t#{changed.map { |d| create_unique_constraint d.new_constraint, table_diff.new_table }.join("\n\t")}"
|
126
|
+
end
|
127
|
+
queries.flatten.join("\n")
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def create_primary_key table, primary_key = nil
|
133
|
+
primary_key = table.primary_key if nil == primary_key
|
134
|
+
columns = primary_key.columns.map {|c| "#{table.name.downcase}['#{c.name}']" }
|
135
|
+
columns = columns.count > 1 ? "[#{columns.join(", ")}]" : columns.first
|
136
|
+
"#{@keywords[:primary_key]}(\"#{primary_key.name}\", #{columns})"
|
137
|
+
end
|
138
|
+
|
139
|
+
def create_check_constraint constraint
|
140
|
+
"#{@keywords[:check_constraint]}(\"#{constraint.name}\", \"#{constraint.condition}\")"
|
141
|
+
end
|
142
|
+
|
143
|
+
def create_unique_constraint constraint, table
|
144
|
+
columns = constraint.columns.map {|c| "#{table.name.downcase}['#{c.name}']" }
|
145
|
+
columns = columns.count > 1 ? "[#{columns.join(", ")}]" : columns.first
|
146
|
+
"#{@keywords[:unique_constraint]}(\"#{constraint.name}\", #{columns})"
|
147
|
+
end
|
148
|
+
|
149
|
+
def collect_columns table
|
150
|
+
columns = table.columns.sort { |a,b| a.order <=> b.order }.map { |c| @column_renderer.create c }
|
151
|
+
if columns.count > 1
|
152
|
+
if @options[:pretty]
|
153
|
+
":columns => [\n\t#{columns.join(",\n\t")}\n]"
|
154
|
+
else
|
155
|
+
":columns => [#{columns.join(", ")}]"
|
156
|
+
end
|
157
|
+
elsif columns.count > 0
|
158
|
+
":columns => #{columns.first}"
|
159
|
+
else
|
160
|
+
""
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def collect_constraints table
|
165
|
+
items = []
|
166
|
+
if nil != table.primary_key then items << "#{table.name.downcase}.add(#{create_primary_key(table)})" end
|
167
|
+
items << table.check_constraints.map { |c| "#{table.name.downcase}.add(#{create_check_constraint c})" }
|
168
|
+
items << table.unique_constraints.map { |c| "#{table.name.downcase}.add(#{create_unique_constraint c, table})" }
|
169
|
+
items << table.foreign_keys.map { |k| "#{table.name.downcase}.add(#{@fk_renderer.create k})" }
|
170
|
+
items.flatten.compact
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|