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,23 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Defines database function
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'operation'
|
6
|
+
|
7
|
+
module Dbsketch
|
8
|
+
module Model
|
9
|
+
|
10
|
+
class Function < Operation
|
11
|
+
def initialize name, meaning: nil, comment: nil, dependencies: [], arguments: [], returns:, algo:
|
12
|
+
super name, :meaning => meaning, :comment => comment, :dependencies => dependencies, :arguments => arguments, :algo => algo
|
13
|
+
### Preconditions
|
14
|
+
raise ArgumentError, "returns is not a String" unless returns.is_a? String
|
15
|
+
###
|
16
|
+
@returns = returns
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :returns
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Defines database column
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'abstract_column'
|
6
|
+
require_relative 'computed_column'
|
7
|
+
require_relative 'database_object'
|
8
|
+
require_relative 'table'
|
9
|
+
require_relative 'model_error'
|
10
|
+
require_relative 'view'
|
11
|
+
|
12
|
+
module Dbsketch
|
13
|
+
module Model
|
14
|
+
|
15
|
+
class Index < Database_Object
|
16
|
+
def initialize name, target, columns, meaning: nil, comment: nil, dependencies: []
|
17
|
+
super name, :meaning => meaning, :comment => comment, :dependencies => dependencies
|
18
|
+
@columns = columns.is_a?(Array) ? columns : [columns]
|
19
|
+
### Preconditions
|
20
|
+
raise ArgumentError, "target is not a Dbsketch::Model::Table or a View" unless target.is_a? Table or target.is_a? View
|
21
|
+
@columns.each_with_index do |column, index|
|
22
|
+
raise ArgumentError, "columns[#{index}] is not a Dbsketch::Model::AbstractColumn" unless column.is_a? AbstractColumn
|
23
|
+
raise ModelError, "computed column #{column.name} is not persisted" if column.is_a? ComputedColumn and not column.persisted
|
24
|
+
end
|
25
|
+
###
|
26
|
+
@target = target
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :target, :columns
|
30
|
+
|
31
|
+
def has_column? column_name
|
32
|
+
### Preconditions
|
33
|
+
raise ArgumentError, "column_name is not a String" unless column_name.is_a? String
|
34
|
+
###
|
35
|
+
nil != @columns.find { |c| c.name.downcase == column_name.downcase }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Represents database model error (for example, two columns with a same name in a table)
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
module Dbsketch
|
6
|
+
module Model
|
7
|
+
|
8
|
+
class ModelError < StandardError
|
9
|
+
def initialize message
|
10
|
+
super(message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Defines database operation (function and procedure common stuff)
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'database_object'
|
6
|
+
|
7
|
+
module Dbsketch
|
8
|
+
module Model
|
9
|
+
|
10
|
+
class Operation < Database_Object
|
11
|
+
def initialize name, meaning: nil, comment: nil, dependencies: [], arguments: [], algo:
|
12
|
+
super name, :meaning => meaning, :comment => comment, :dependencies => dependencies
|
13
|
+
arguments = arguments.is_a?(Array) ? arguments : [arguments]
|
14
|
+
### Preconditions
|
15
|
+
arguments.each_with_index do |arg, index|
|
16
|
+
raise ArgumentError, "arguments[#{index}] is not a String" unless arg.is_a? String
|
17
|
+
end
|
18
|
+
raise ArgumentError, "algo is not a String" unless algo.is_a? String
|
19
|
+
###
|
20
|
+
@arguments = arguments
|
21
|
+
@algo = algo
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :algo, :arguments
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Primary Key
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'column'
|
6
|
+
require_relative 'database_object'
|
7
|
+
|
8
|
+
module Dbsketch
|
9
|
+
module Model
|
10
|
+
|
11
|
+
class PrimaryKey < 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,18 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Defines database stored procedure
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'operation'
|
6
|
+
|
7
|
+
module Dbsketch
|
8
|
+
module Model
|
9
|
+
|
10
|
+
class Procedure < Operation
|
11
|
+
def initialize name, meaning: nil, comment: nil, dependencies: [], arguments: [], algo:
|
12
|
+
super name, :meaning => meaning, :comment => comment, :dependencies => dependencies, :arguments => arguments, :algo => algo
|
13
|
+
# TODO check arguments are one of [out, output, readonly]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Defines database table structure
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'abstract_column'
|
6
|
+
require_relative 'check_constraint'
|
7
|
+
require_relative 'column'
|
8
|
+
require_relative 'database_object'
|
9
|
+
require_relative 'foreign_key'
|
10
|
+
require_relative 'model_error'
|
11
|
+
require_relative 'primary_key'
|
12
|
+
require_relative 'unique_constraint'
|
13
|
+
|
14
|
+
module Dbsketch
|
15
|
+
module Model
|
16
|
+
|
17
|
+
class Table < Database_Object
|
18
|
+
def initialize name, meaning: nil, comment: nil, dependencies: [], columns: [], p_key_columns: []
|
19
|
+
super name, :meaning => meaning, :comment => comment, :dependencies => dependencies
|
20
|
+
columns = columns.is_a?(Array) ? columns.flatten : [columns]
|
21
|
+
p_key_columns = p_key_columns.is_a?(Array) ? p_key_columns : [p_key_columns]
|
22
|
+
### Preconditions
|
23
|
+
columns.each_with_index do |column, index|
|
24
|
+
raise ArgumentError, "columns[#{index}] is not a Dbsketch::Model::AbstractColumn" unless column.is_a? AbstractColumn
|
25
|
+
end
|
26
|
+
p_key_columns.each_with_index do |column, index|
|
27
|
+
raise ArgumentError, "p_key_columns[#{index}] is not a String nor a Dbsketch::Model::AbstractColumn" unless column.is_a? String or column.is_a? AbstractColumn
|
28
|
+
end
|
29
|
+
###
|
30
|
+
@columns = []
|
31
|
+
columns.each { |c| add_column c }
|
32
|
+
@primary_key = nil
|
33
|
+
primary_key_columns = p_key_columns.map { |c| (c.is_a? AbstractColumn) ? c : self[c] }
|
34
|
+
set_primary_key PrimaryKey.new "PK_#{@name}", primary_key_columns if not primary_key_columns.empty?
|
35
|
+
@check_constraints = []
|
36
|
+
@foreign_keys = []
|
37
|
+
@unique_constraints = []
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :columns, :primary_key, :check_constraints, :foreign_keys, :unique_constraints
|
41
|
+
|
42
|
+
def add object
|
43
|
+
objects = object.is_a?(Array) ? object : [object]
|
44
|
+
### Preconditions
|
45
|
+
objects.each_with_index do |o, index|
|
46
|
+
raise ArgumentError, "object n°#{index + 1} is not a valid Dbsketch::Model object" unless o.is_a? AbstractColumn or o.is_a? PrimaryKey or o.is_a? CheckConstraint or o.is_a? ForeignKey or o.is_a? UniqueConstraint
|
47
|
+
end
|
48
|
+
###
|
49
|
+
objects.each do |o|
|
50
|
+
if o.is_a? AbstractColumn
|
51
|
+
add_column o
|
52
|
+
elsif o.is_a? PrimaryKey
|
53
|
+
set_primary_key o
|
54
|
+
elsif o.is_a? CheckConstraint
|
55
|
+
add_check_constraint o
|
56
|
+
elsif o.is_a? ForeignKey
|
57
|
+
add_foreign_key o
|
58
|
+
elsif o.is_a? UniqueConstraint
|
59
|
+
add_unique_constraint o
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def has_column? column_name
|
65
|
+
### Preconditions
|
66
|
+
raise ArgumentError, "column_name is not a String" unless column_name.is_a? String
|
67
|
+
###
|
68
|
+
nil != @columns.find { |c| c.name.downcase == column_name.downcase }
|
69
|
+
end
|
70
|
+
|
71
|
+
def has_check_constraint? constraint_name
|
72
|
+
### Preconditions
|
73
|
+
raise ArgumentError, "constraint_name is not a String" unless constraint_name.is_a? String
|
74
|
+
###
|
75
|
+
nil != @check_constraints.find { |c| c.name.downcase == constraint_name.downcase }
|
76
|
+
end
|
77
|
+
|
78
|
+
def has_foreign_key? key_name
|
79
|
+
### Preconditions
|
80
|
+
raise ArgumentError, "key_name is not a String" unless key_name.is_a? String
|
81
|
+
###
|
82
|
+
nil != @foreign_keys.find { |c| c.name.downcase == key_name.downcase }
|
83
|
+
end
|
84
|
+
|
85
|
+
def has_unique_constraint? constraint_name
|
86
|
+
### Preconditions
|
87
|
+
raise ArgumentError, "constraint_name is not a String" unless constraint_name.is_a? String
|
88
|
+
###
|
89
|
+
nil != @unique_constraints.find { |c| c.name.downcase == constraint_name.downcase }
|
90
|
+
end
|
91
|
+
|
92
|
+
def [] column_name
|
93
|
+
column = @columns.find { |c| c.name.downcase == column_name.downcase }
|
94
|
+
raise ArgumentError, "column #{column_name} not found in table #{@name}" if nil == column
|
95
|
+
column
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_constraint constraint_name
|
99
|
+
constraint = @check_constraints.find { |c| c.name.downcase == constraint_name.downcase }
|
100
|
+
raise ArgumentError, "check constraint #{constraint_name} not found in table #{@name}" if nil == constraint
|
101
|
+
constraint
|
102
|
+
end
|
103
|
+
|
104
|
+
def foreign_key key_name
|
105
|
+
key = @foreign_keys.find { |c| c.name.downcase == key_name.downcase }
|
106
|
+
raise ArgumentError, "foreign key #{key_name} not found in table #{@name}" if nil == key
|
107
|
+
key
|
108
|
+
end
|
109
|
+
|
110
|
+
def unique_constraint constraint_name
|
111
|
+
constraint = @unique_constraints.find { |c| c.name.downcase == constraint_name.downcase }
|
112
|
+
raise ArgumentError, "unique constraint #{constraint_name} not found in table #{@name}" if nil == constraint
|
113
|
+
constraint
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def add_column column
|
119
|
+
### Preconditions
|
120
|
+
raise ModelError, "column #{column.name} already exists in table #{@name}" if nil != (@columns.find { |c| c.name.downcase == column.name.downcase })
|
121
|
+
raise ModelError, "column #{column.name} has an order but column without order exists in table #{@name}" if nil != column.order and nil != (@columns.find { |c| nil == c.order })
|
122
|
+
raise ModelError, "a column of order #{column.order} already exists in table #{@name}" if nil != (@columns.find { |c| nil != c.order and c.order == column.order })
|
123
|
+
###
|
124
|
+
@columns << column
|
125
|
+
end
|
126
|
+
|
127
|
+
def set_primary_key key
|
128
|
+
### Preconditions
|
129
|
+
raise ModelError, "a primary key already exists in table #{@name}" if nil != @primary_key
|
130
|
+
key.columns.each do |pk_c|
|
131
|
+
raise ModelError, "primary key column #{pk_c.name} does not exists in table #{@name}" if nil == (@columns.find { |c| c.name.downcase == pk_c.name.downcase })
|
132
|
+
end
|
133
|
+
###
|
134
|
+
@primary_key = key
|
135
|
+
end
|
136
|
+
|
137
|
+
def constraint_exist? constraint
|
138
|
+
(nil != (@check_constraints.find { |c| c.name.downcase == constraint.name.downcase }) or
|
139
|
+
nil != (@foreign_keys.find { |k| k.name.downcase == constraint.name.downcase }) or
|
140
|
+
nil != (@unique_constraints.find { |c| c.name.downcase == constraint.name.downcase }))
|
141
|
+
end
|
142
|
+
|
143
|
+
def add_check_constraint constraint
|
144
|
+
### Preconditions
|
145
|
+
raise ModelError, "constraint #{constraint.name} already exists in table #{@name}" if constraint_exist? constraint
|
146
|
+
###
|
147
|
+
@check_constraints << constraint
|
148
|
+
end
|
149
|
+
|
150
|
+
def add_foreign_key constraint
|
151
|
+
### Preconditions
|
152
|
+
raise ModelError, "constraint #{constraint.name} already exists in table #{@name}" if constraint_exist? constraint
|
153
|
+
raise ModelError, "constraint #{constraint.name} column #{constraint.constricted_column.name} does not exists in table #{@name}" if nil == (@columns.find { |c| c.name.downcase == constraint.constricted_column.name.downcase })
|
154
|
+
###
|
155
|
+
@foreign_keys << constraint
|
156
|
+
add_dependencies constraint.referenced_table
|
157
|
+
end
|
158
|
+
|
159
|
+
def add_unique_constraint constraint
|
160
|
+
### Preconditions
|
161
|
+
raise ModelError, "constraint #{constraint.name} already exists in table #{@name}" if constraint_exist? constraint
|
162
|
+
constraint.columns.each do |uc_c|
|
163
|
+
raise ModelError, "constraint column #{uc_c.name} does not exists in table #{@name}" if nil == (@columns.find { |c| c.name.downcase == uc_c.name.downcase })
|
164
|
+
end
|
165
|
+
###
|
166
|
+
@unique_constraints << constraint
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Defines database trigger
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
require_relative 'database_object'
|
6
|
+
require_relative 'model_error'
|
7
|
+
require_relative 'table'
|
8
|
+
require_relative 'view'
|
9
|
+
|
10
|
+
module Dbsketch
|
11
|
+
module Model
|
12
|
+
|
13
|
+
class Trigger < Database_Object
|
14
|
+
def initialize name, target, activation_time, algo:, meaning: nil, comment: nil, dependencies: []
|
15
|
+
super name, :meaning => meaning, :comment => comment, :dependencies => dependencies
|
16
|
+
### Preconditions
|
17
|
+
raise ArgumentError, "target is not a Dbsketch::Model::Table or View" unless target.is_a? Table or target.is_a? View
|
18
|
+
raise ArgumentError, "activation_time is not a String" unless activation_time.is_a? String
|
19
|
+
raise ModelError, "activation_time does not begins 'for', 'after' or 'instead of' (#{activation_time})" if nil == activation_time.downcase.match(/^(for)|(after)|(instead of)/)
|
20
|
+
raise ArgumentError, "algo is not a String" unless algo.is_a? String
|
21
|
+
###
|
22
|
+
@target = target
|
23
|
+
@activation_time = activation_time
|
24
|
+
@algo = algo
|
25
|
+
add_dependencies target
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :target, :activation_time, :algo
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
########################################################################################################################
|
2
|
+
# Represents database type, allow to check compatibility
|
3
|
+
########################################################################################################################
|
4
|
+
|
5
|
+
module Dbsketch
|
6
|
+
module Model
|
7
|
+
|
8
|
+
class Type
|
9
|
+
def initialize(sql_type, sizes = [])
|
10
|
+
@sizes = sizes.is_a?(Array) ? sizes : [sizes]
|
11
|
+
### Preconditions
|
12
|
+
raise ArgumentError, "sql_type is not a String" unless sql_type.is_a? String
|
13
|
+
@sizes.each do |size|
|
14
|
+
if 'max' == size
|
15
|
+
if not ['varchar', 'nvarchar'].include? sql_type
|
16
|
+
raise ArgumentError, "size 'max' allowed only for [n]varchar"
|
17
|
+
end
|
18
|
+
elsif not size.is_a? Fixnum and not size.is_a? Integer
|
19
|
+
raise ArgumentError, "size #{size} of sql type #{sql_type} is not a number"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
raise ArgumentError, "#{sql_type} do not allow defining sizes" if ['datetime', 'datetime2', 'int'].include? sql_type and @sizes.count > 0
|
23
|
+
raise ArgumentError, "#{sql_type} do not allow more than one size" if sql_type.match(/(n){0,1}(var){0,1}char/) and @sizes.count > 1
|
24
|
+
raise ArgumentError, "#{sql_type} need at least a precision, but no sizes were given" if ['decimal', 'numeric'].include? sql_type and @sizes.count == 0
|
25
|
+
raise ArgumentError, "defining more than 2 sizes for #{sql_type}" if @sizes.count > 2
|
26
|
+
###
|
27
|
+
@sql_type = sql_type
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :sql_type, :sizes
|
31
|
+
|
32
|
+
# Return true if current type can be stored in other_type without error nor information loss
|
33
|
+
def compatible_with? other_type
|
34
|
+
### Preconditions
|
35
|
+
raise ArgumentError, "other_type is not a Dbsketch::Model::Type" unless other_type.is_a? Dbsketch::Model::Type
|
36
|
+
###
|
37
|
+
# TODO enhance this function (numeric and int may be compatible with particular sizes)
|
38
|
+
compatible = false
|
39
|
+
|
40
|
+
if :numeric == get_category(@sql_type)
|
41
|
+
if :numeric == get_category(other_type.sql_type)
|
42
|
+
compatible = size_compatibile_with? other_type.sizes
|
43
|
+
end
|
44
|
+
elsif :datetime == get_category(@sql_type)
|
45
|
+
compatible = (:datetime == get_category(other_type.sql_type))
|
46
|
+
elsif :string == get_category(@sql_type)
|
47
|
+
compatible = false
|
48
|
+
if :string == get_category(other_type.sql_type)
|
49
|
+
if (@sql_type.match(/^(var){0,1}char$/) and other_type.sql_type.match(/^(var){0,1}char$/)) or
|
50
|
+
(@sql_type.match(/^n(var){0,1}char$/) and other_type.sql_type.match(/^n(var){0,1}char$/))
|
51
|
+
compatible = size_compatibile_with? other_type.sizes
|
52
|
+
end
|
53
|
+
end
|
54
|
+
elsif :boolean == get_category(@sql_type)
|
55
|
+
compatible = (:boolean == get_category(other_type.sql_type))
|
56
|
+
end
|
57
|
+
compatible
|
58
|
+
end
|
59
|
+
|
60
|
+
def category
|
61
|
+
get_category(@sql_type)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def get_category sql_type
|
67
|
+
if ['decimal', 'int', 'numeric'].include? sql_type
|
68
|
+
:numeric
|
69
|
+
elsif ['datetime', 'datetime2'].include? sql_type
|
70
|
+
:datetime
|
71
|
+
elsif sql_type.match(/(n){0,1}(var){0,1}char/)
|
72
|
+
:string
|
73
|
+
elsif 'bit' == sql_type
|
74
|
+
:boolean
|
75
|
+
else
|
76
|
+
:unknown
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def size_compatibile_with? other_sizes
|
81
|
+
compatible = false
|
82
|
+
if @sizes.empty? and other_sizes.empty?
|
83
|
+
compatible = true
|
84
|
+
elsif not @sizes.empty? and not other_sizes.empty?
|
85
|
+
compatible = (@sizes.first <= other_sizes.first)
|
86
|
+
end
|
87
|
+
compatible
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|