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,58 @@
1
+ ########################################################################################################################
2
+ # Database differences between two existing unique constraint
3
+ ########################################################################################################################
4
+
5
+ require_relative '../model/unique_constraint'
6
+ require_relative 'diff'
7
+
8
+ module Dbsketch
9
+ module Comparison
10
+
11
+ class UniqueConstraintDiff < Diff
12
+ def initialize old_constraint, new_constraint, columns
13
+ super old_constraint, new_constraint
14
+ ### Preconditions
15
+ columns.each_with_index { |column, index| raise ArgumentError, "columns[#{index}] is not a Dbsketch::Comparison::Diff" unless column.is_a? Dbsketch::Comparison::Diff }
16
+ ###
17
+ @columns = columns
18
+ end
19
+
20
+ attr_reader :columns
21
+ alias :old_constraint :old_value
22
+ alias :new_constraint :new_value
23
+ end
24
+
25
+ class UniqueConstraintComparator
26
+
27
+ def are_equivalent? old_constraint, new_constraint
28
+ ### Preconditions
29
+ raise ArgumentError, "old_constraint is not a Dbsketch::Model::UniqueConstraint" unless nil == old_constraint or old_constraint.is_a? Dbsketch::Model::UniqueConstraint
30
+ raise ArgumentError, "new_constraint is not a Dbsketch::Model::UniqueConstraint" unless nil == new_constraint or new_constraint.is_a? Dbsketch::Model::UniqueConstraint
31
+ ###
32
+ (nil != old_constraint and nil != new_constraint) and columns(old_constraint, new_constraint).empty?
33
+ end
34
+
35
+ # Returns a UniqueConstraintDiff if tables are different, nil otherwise
36
+ def compare old_constraint, new_constraint
37
+ ### Preconditions
38
+ raise ArgumentError, "old_constraint is not a Dbsketch::Model::UniqueConstraint" unless nil == old_constraint or old_constraint.is_a? Dbsketch::Model::UniqueConstraint
39
+ raise ArgumentError, "new_constraint is not a Dbsketch::Model::UniqueConstraint" unless nil == new_constraint or new_constraint.is_a? Dbsketch::Model::UniqueConstraint
40
+ ###
41
+ UniqueConstraintDiff.new(old_constraint, new_constraint, columns(old_constraint, new_constraint)) if not are_equivalent? old_constraint, new_constraint
42
+ end
43
+
44
+ private
45
+
46
+ def columns old_constraint, new_constraint
47
+ diffs = []
48
+ if nil != old_constraint and nil != new_constraint
49
+ diffs << old_constraint.columns.select { |old_c| not new_constraint.has_column? old_c.name }.map { |old_c| Diff.new old_c.name, nil }
50
+ diffs << new_constraint.columns.select { |new_c| not old_constraint.has_column? new_c.name }.map { |new_c| Diff.new nil, new_c.name }
51
+ end
52
+ diffs.flatten.compact
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,54 @@
1
+ ########################################################################################################################
2
+ # Compute differences between two existing check constraint
3
+ ########################################################################################################################
4
+
5
+ require_relative '../model/view'
6
+ require_relative 'comparison_error'
7
+ require_relative 'diff'
8
+
9
+ module Dbsketch
10
+ module Comparison
11
+
12
+ class ViewDiff < Diff
13
+ def initialize old_view, new_view
14
+ super old_view, new_view
15
+ end
16
+ alias :old_view :old_value
17
+ alias :new_view :new_value
18
+
19
+ def query
20
+ ### Preconditions
21
+ raise ComparisonError, "no change found" if not change?
22
+ ###
23
+ Diff.new old_view.query, new_view.query
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ module Dbsketch
31
+ module Comparison
32
+
33
+ class ViewComparator
34
+
35
+ def are_equivalent? old_view, new_view
36
+ ### Preconditions
37
+ raise ArgumentError, "old_view is not a Dbsketch::Model::View" unless nil == old_view or old_view.is_a? Dbsketch::Model::View
38
+ raise ArgumentError, "new_view is not a Dbsketch::Model::View" unless nil == new_view or new_view.is_a? Dbsketch::Model::View
39
+ ###
40
+ (nil != old_view and nil != new_view) and (old_view.query == new_view.query)
41
+ end
42
+
43
+ def compare old_view, new_view
44
+ ### Preconditions
45
+ raise ArgumentError, "old_view is not a Dbsketch::Model::View" unless nil == old_view or old_view.is_a? Dbsketch::Model::View
46
+ raise ArgumentError, "new_view is not a Dbsketch::Model::View" unless nil == new_view or new_view.is_a? Dbsketch::Model::View
47
+ ###
48
+ ViewDiff.new(old_view, new_view) if not are_equivalent? old_view, new_view
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,25 @@
1
+ ########################################################################################################################
2
+ # Common structure for database columns
3
+ ########################################################################################################################
4
+
5
+ require_relative 'database_object'
6
+
7
+ module Dbsketch
8
+ module Model
9
+
10
+ class AbstractColumn < Database_Object
11
+ def initialize name, meaning: nil, comment: nil, nullable: true, order: nil
12
+ super name, :meaning => meaning, :comment => comment
13
+ ### Preconditions
14
+ raise ArgumentError, "nullable is not a boolean" unless nullable.is_a? TrueClass or nullable.is_a? FalseClass
15
+ raise ArgumentError, "order is not an Integer" unless nil == order or order.is_a? Integer
16
+ ###
17
+ @nullable = nullable
18
+ @order = order
19
+ end
20
+
21
+ attr_reader :nullable, :order
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ ########################################################################################################################
2
+ # Check constraint
3
+ ########################################################################################################################
4
+
5
+ require_relative 'database_object'
6
+
7
+ module Dbsketch
8
+ module Model
9
+
10
+ class CheckConstraint < Database_Object
11
+ def initialize name, condition, meaning: nil, comment: nil
12
+ super name, :meaning => meaning, :comment => comment
13
+ ### Preconditions
14
+ raise ArgumentError, "condition is not a String" unless condition.is_a? String
15
+ ###
16
+ @condition = condition
17
+ end
18
+
19
+ attr_reader :condition
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ ########################################################################################################################
2
+ # Defines database column
3
+ ########################################################################################################################
4
+
5
+ require_relative 'abstract_column'
6
+ require_relative 'type'
7
+
8
+ module Dbsketch
9
+ module Model
10
+
11
+ class Column < AbstractColumn
12
+ def initialize name, type, meaning: nil, comment: nil, nullable: true, order: nil, identity: false, default: nil
13
+ super(name, :meaning => meaning, :comment => comment, :nullable => nullable, :order => order)
14
+ ### Preconditions
15
+ raise ArgumentError, "type is not a Dbsketch::Model::Type" unless type.is_a? Dbsketch::Model::Type
16
+ raise ArgumentError, "identity is not a boolean" unless identity.is_a? TrueClass or identity.is_a? FalseClass
17
+ ###
18
+ @type = type
19
+ @identity = identity
20
+ @default = default
21
+ end
22
+
23
+ attr_reader :type, :identity, :default
24
+ attr_writer :default
25
+
26
+ def compatible_with? other_column
27
+ ### Preconditions
28
+ raise ArgumentError, "other_column is not a Dbsketch::Model::Column" unless other_column.is_a? Column
29
+ ###
30
+ (@type.compatible_with? other_column.type) and (not @nullable or other_column.nullable)
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ ########################################################################################################################
2
+ # Defines database computed column
3
+ ########################################################################################################################
4
+
5
+ require_relative 'abstract_column'
6
+ require_relative 'model_error'
7
+
8
+ module Dbsketch
9
+ module Model
10
+
11
+ class ComputedColumn < AbstractColumn
12
+ def initialize name, query, meaning: nil, comment: nil, nullable: true, order: nil, persisted: false
13
+ super(name, :meaning => meaning, :comment => comment, :nullable => nullable, :order => order)
14
+ ### Preconditions
15
+ raise ArgumentError, "query is not a String" unless query.is_a? String
16
+ raise ArgumentError, "persisted is not a boolean" unless persisted.is_a? TrueClass or persisted.is_a? FalseClass
17
+ raise ModelError, "column is not persisted althought not nullable" if not nullable and not persisted
18
+ ###
19
+ @query = query
20
+ @persisted = persisted
21
+ end
22
+
23
+ attr_reader :query, :persisted
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ ########################################################################################################################
2
+ # Defines database custom code, so developers can write specific code
3
+ ########################################################################################################################
4
+
5
+ require_relative 'database_object'
6
+
7
+ module Dbsketch
8
+ module Model
9
+
10
+ class CustomCode < Database_Object
11
+ def initialize name, do_code, undo_code: nil, meaning: nil, comment: nil, dependencies: []
12
+ super name, :meaning => meaning, :comment => comment, :dependencies => dependencies
13
+ @do_code = do_code
14
+ @undo_code = undo_code
15
+ end
16
+
17
+ attr_reader :do_code, :undo_code
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,87 @@
1
+ ########################################################################################################################
2
+ # Database representation
3
+ ########################################################################################################################
4
+
5
+ require_relative 'custom_code'
6
+ require_relative 'index'
7
+ require_relative 'model_error'
8
+ require_relative 'operation'
9
+ require_relative 'table'
10
+ require_relative 'trigger'
11
+ require_relative 'view'
12
+
13
+ module Dbsketch
14
+ module Model
15
+
16
+ class Database
17
+ def initialize
18
+ @items = []
19
+ end
20
+
21
+ attr_reader :items
22
+
23
+ def add object
24
+ objects = object.is_a?(Array) ? object : [object]
25
+ ### Preconditions
26
+ objects.each_with_index do |o, index|
27
+ raise ArgumentError, "object n°#{index + 1} is not a Dbsketch::Model::CustomCode, Index, Operation, Table nor View" unless o.is_a? CustomCode or o.is_a? Index or o.is_a? Operation or o.is_a? Table or o.is_a? Trigger or o.is_a? View
28
+ raise ModelError, "object #{o.name} already exists" if nil != (@items.find { |i| i.name.downcase == o.name.downcase })
29
+ end
30
+ ###
31
+ @items = @items + objects
32
+ end
33
+
34
+ def get_by_class given_class
35
+ @items.select { |i| i.is_a? given_class }
36
+ end
37
+
38
+ def custom_code
39
+ get_by_class CustomCode
40
+ end
41
+
42
+ def indexes
43
+ get_by_class Index
44
+ end
45
+
46
+ def operations
47
+ get_by_class Operation
48
+ end
49
+
50
+ def tables
51
+ get_by_class Table
52
+ end
53
+
54
+ def triggers
55
+ get_by_class Trigger
56
+ end
57
+
58
+ def views
59
+ get_by_class View
60
+ end
61
+
62
+ def has_item? item_name
63
+ ### Preconditions
64
+ raise ArgumentError, "item_name is not a String" unless item_name.is_a? String
65
+ ###
66
+ nil != @items.find { |t| t.name.downcase == item_name.downcase }
67
+ end
68
+
69
+ def [] item_name
70
+ ### Preconditions
71
+ raise ArgumentError, "item_name is not a String" unless item_name.is_a? String
72
+ ###
73
+ item = @items.find { |t| t.name.downcase == item_name.downcase }
74
+ raise ModelError, "item #{item_name} not found in database" if nil == item
75
+ item
76
+ end
77
+
78
+ def order_items!
79
+ @items.map! { |i| i.reset_order!; i }
80
+ @items.map! { |i| i.compute_order!; i }
81
+ @items.sort! { |a,b| (a.order != b.order) ? (a.order <=> b.order) : (a.name <=> b.name) }
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,71 @@
1
+ ########################################################################################################################
2
+ # Defines database common object
3
+ ########################################################################################################################
4
+
5
+ require_relative 'model_error'
6
+
7
+ module Dbsketch
8
+ module Model
9
+
10
+ class Database_Object
11
+ def initialize name, meaning: nil, comment: nil, dependencies: []
12
+ dependencies = dependencies.is_a?(Array) ? dependencies : [dependencies]
13
+ ### Preconditions
14
+ raise ArgumentError, "name is not a String" unless name.is_a? String
15
+ raise ModelError, "name (#{name}) shall not contain special chars (apart from underscore)" if name.match(/\W/)
16
+ raise ArgumentError, "meaning is not a String" unless nil == meaning or meaning.is_a? String
17
+ raise ArgumentError, "comment is not a String" unless nil == comment or comment.is_a? String
18
+ dependencies.each_with_index do |d, index|
19
+ raise ArgumentError, "dependencies[#{index}] is not a Dbsketch::Model::Database_Object" unless d.is_a? Database_Object
20
+ end
21
+ ###
22
+ @name = name
23
+ @meaning = meaning
24
+ @comment = comment
25
+ @dependencies = dependencies
26
+ @order = nil
27
+ end
28
+
29
+ attr_reader :name, :meaning, :comment, :dependencies, :order
30
+
31
+ def add_dependencies dependencies
32
+ dependencies = dependencies.is_a?(Array) ? dependencies : [dependencies]
33
+ ### Preconditions
34
+ dependencies.each_with_index do |d, index|
35
+ raise ArgumentError, "dependencies[#{index}] is not a Dbsketch::Model::Database_Object" unless d.is_a? Database_Object
36
+ end
37
+ ###
38
+ @dependencies = (@dependencies.concat(dependencies)).uniq
39
+ end
40
+
41
+ def class_name
42
+ self.class.name.gsub(/^Dbsketch::Model::/, '')
43
+ end
44
+
45
+ def inspect
46
+ "#{self.class_name}:#{object_id} #{@name}"
47
+ end
48
+
49
+ def reset_order!
50
+ @order = nil
51
+ end
52
+
53
+ def compute_order! trace = []
54
+ if nil == @order
55
+ current_trace = trace.clone
56
+ current_trace << self
57
+ if nil != trace.find { |t| t.object_id == self.object_id }
58
+ raise ModelError, "circular dependencies found. Trace: #{current_trace.map { |t| "#{t.class_name} #{t.name}" }.join(" < ")}"
59
+ end
60
+ if @dependencies.empty?
61
+ @order = 1
62
+ else
63
+ @order = @dependencies.map {|d| d.compute_order! current_trace }.max + 1
64
+ end
65
+ end
66
+ @order
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,29 @@
1
+ ########################################################################################################################
2
+ # Primary Key
3
+ ########################################################################################################################
4
+
5
+ require_relative 'column'
6
+ require_relative 'database_object'
7
+ require_relative 'table'
8
+
9
+ module Dbsketch
10
+ module Model
11
+
12
+ class ForeignKey < Database_Object
13
+ def initialize name, constricted_column, referenced_table, referenced_column, meaning: nil, comment: nil
14
+ super name, :meaning => meaning, :comment => comment
15
+ ### Preconditions
16
+ raise ArgumentError, "constricted column is not a Dbsketch::Model::Column" unless constricted_column.is_a? Column
17
+ raise ArgumentError, "name is not a Dbsketch::Model::Table" unless referenced_table.is_a? Table
18
+ raise ArgumentError, "referenced column is not a Dbsketch::Model::Column" unless referenced_column.is_a? Column
19
+ ###
20
+ @constricted_column = constricted_column
21
+ @referenced_table = referenced_table
22
+ @referenced_column = referenced_column
23
+ end
24
+
25
+ attr_reader :constricted_column, :referenced_table, :referenced_column
26
+ end
27
+
28
+ end
29
+ end