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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +1 -0
  4. data/lib/dbsketch.rb +64 -0
  5. data/lib/dbsketch/automation/automation_error.rb +15 -0
  6. data/lib/dbsketch/automation/database_connection_details.rb +32 -0
  7. data/lib/dbsketch/automation/database_importer.rb +184 -0
  8. data/lib/dbsketch/automation/database_proxy.rb +78 -0
  9. data/lib/dbsketch/automation/table_importer.rb +114 -0
  10. data/lib/dbsketch/comparison/check_constraint_comparator.rb +54 -0
  11. data/lib/dbsketch/comparison/column_comparator.rb +65 -0
  12. data/lib/dbsketch/comparison/comparison_error.rb +15 -0
  13. data/lib/dbsketch/comparison/computed_column_comparator.rb +63 -0
  14. data/lib/dbsketch/comparison/database_comparator.rb +115 -0
  15. data/lib/dbsketch/comparison/diff.rb +37 -0
  16. data/lib/dbsketch/comparison/foreign_key_comparator.rb +56 -0
  17. data/lib/dbsketch/comparison/function_comparator.rb +56 -0
  18. data/lib/dbsketch/comparison/index_comparator.rb +65 -0
  19. data/lib/dbsketch/comparison/primary_key_comparator.rb +61 -0
  20. data/lib/dbsketch/comparison/procedure_comparator.rb +54 -0
  21. data/lib/dbsketch/comparison/table_comparator.rb +158 -0
  22. data/lib/dbsketch/comparison/trigger_comparator.rb +53 -0
  23. data/lib/dbsketch/comparison/type_comparator.rb +51 -0
  24. data/lib/dbsketch/comparison/unique_constraint_comparator.rb +58 -0
  25. data/lib/dbsketch/comparison/view_comparator.rb +54 -0
  26. data/lib/dbsketch/model/abstract_column.rb +25 -0
  27. data/lib/dbsketch/model/check_constraint.rb +23 -0
  28. data/lib/dbsketch/model/column.rb +35 -0
  29. data/lib/dbsketch/model/computed_column.rb +27 -0
  30. data/lib/dbsketch/model/custom_code.rb +21 -0
  31. data/lib/dbsketch/model/database.rb +87 -0
  32. data/lib/dbsketch/model/database_object.rb +71 -0
  33. data/lib/dbsketch/model/foreign_key.rb +29 -0
  34. data/lib/dbsketch/model/function.rb +23 -0
  35. data/lib/dbsketch/model/index.rb +40 -0
  36. data/lib/dbsketch/model/model_error.rb +15 -0
  37. data/lib/dbsketch/model/operation.rb +28 -0
  38. data/lib/dbsketch/model/primary_key.rb +33 -0
  39. data/lib/dbsketch/model/procedure.rb +18 -0
  40. data/lib/dbsketch/model/table.rb +171 -0
  41. data/lib/dbsketch/model/trigger.rb +32 -0
  42. data/lib/dbsketch/model/type.rb +92 -0
  43. data/lib/dbsketch/model/unique_constraint.rb +33 -0
  44. data/lib/dbsketch/model/view.rb +23 -0
  45. data/lib/dbsketch/rendering/meta/column_renderer.rb +76 -0
  46. data/lib/dbsketch/rendering/meta/database_renderer.rb +112 -0
  47. data/lib/dbsketch/rendering/meta/foreign_key_renderer.rb +31 -0
  48. data/lib/dbsketch/rendering/meta/index_renderer.rb +30 -0
  49. data/lib/dbsketch/rendering/meta/operation_renderer.rb +66 -0
  50. data/lib/dbsketch/rendering/meta/table_renderer.rb +177 -0
  51. data/lib/dbsketch/rendering/meta/trigger_renderer.rb +31 -0
  52. data/lib/dbsketch/rendering/meta/type_renderer.rb +37 -0
  53. data/lib/dbsketch/rendering/meta/view_renderer.rb +32 -0
  54. data/lib/dbsketch/rendering/sql/column_renderer.rb +75 -0
  55. data/lib/dbsketch/rendering/sql/database_diff_renderer.rb +94 -0
  56. data/lib/dbsketch/rendering/sql/database_renderer.rb +139 -0
  57. data/lib/dbsketch/rendering/sql/foreign_key_renderer.rb +24 -0
  58. data/lib/dbsketch/rendering/sql/index_renderer.rb +31 -0
  59. data/lib/dbsketch/rendering/sql/operation_renderer.rb +64 -0
  60. data/lib/dbsketch/rendering/sql/table_renderer.rb +148 -0
  61. data/lib/dbsketch/rendering/sql/trigger_renderer.rb +31 -0
  62. data/lib/dbsketch/rendering/sql/type_renderer.rb +28 -0
  63. data/lib/dbsketch/rendering/sql/view_renderer.rb +31 -0
  64. data/lib/dbsketch/version.rb +3 -0
  65. 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