k_domain 0.0.1 → 0.0.14
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 +4 -4
- data/.rubocop.yml +39 -1
- data/Gemfile +10 -0
- data/Guardfile +30 -0
- data/Rakefile +3 -4
- data/STORIES.md +63 -0
- data/USAGE.md +19 -0
- data/k_domain.gemspec +4 -0
- data/lib/k_domain/domain_model/load.rb +29 -0
- data/lib/k_domain/domain_model/transform.rb +110 -0
- data/lib/k_domain/domain_model/transform_steps/_.rb +10 -0
- data/lib/k_domain/domain_model/transform_steps/step.rb +142 -0
- data/lib/k_domain/domain_model/transform_steps/step1_attach_db_schema.rb +21 -0
- data/lib/k_domain/domain_model/transform_steps/step2_attach_models.rb +62 -0
- data/lib/k_domain/domain_model/transform_steps/step3_attach_columns.rb +137 -0
- data/lib/k_domain/domain_model/transform_steps/step4_attach_erd_files.rb +454 -0
- data/lib/k_domain/domain_model/transform_steps/step5_attach_dictionary.rb +58 -0
- data/lib/k_domain/domain_model/transform_steps/step8_locate_rails_models.rb +44 -0
- data/lib/k_domain/raw_db_schema/load.rb +29 -0
- data/lib/k_domain/raw_db_schema/transform.rb +82 -0
- data/lib/k_domain/schemas/_.rb +15 -0
- data/lib/k_domain/schemas/database/_.rb +7 -0
- data/lib/k_domain/schemas/database/foreign_key.rb +14 -0
- data/lib/k_domain/schemas/database/index.rb +14 -0
- data/lib/k_domain/schemas/database/schema.rb +31 -0
- data/lib/k_domain/schemas/database/table.rb +32 -0
- data/lib/k_domain/schemas/dictionary.rb +19 -0
- data/lib/k_domain/schemas/domain/_.rb +65 -0
- data/lib/k_domain/schemas/domain/domain.rb +11 -0
- data/lib/k_domain/schemas/domain/erd_file.rb +80 -0
- data/lib/k_domain/schemas/domain/models/column.rb +49 -0
- data/lib/k_domain/schemas/domain/models/model.rb +111 -0
- data/lib/k_domain/schemas/domain/old/belongs_to.rb +25 -0
- data/lib/k_domain/schemas/domain/old/column_old.rb +225 -0
- data/lib/k_domain/schemas/domain/old/domain_statistics.rb +29 -0
- data/lib/k_domain/schemas/domain/old/entity.rb +338 -0
- data/lib/k_domain/schemas/domain/old/entity_statistics.rb +22 -0
- data/lib/k_domain/schemas/domain/old/foreign_key.rb +17 -0
- data/lib/k_domain/schemas/domain/old/has_and_belongs_to_many.rb +20 -0
- data/lib/k_domain/schemas/domain/old/has_many.rb +27 -0
- data/lib/k_domain/schemas/domain/old/has_one.rb +41 -0
- data/lib/k_domain/schemas/domain/old/name_options.rb +10 -0
- data/lib/k_domain/schemas/domain/old/rails_controller.rb +10 -0
- data/lib/k_domain/schemas/domain/old/rails_model.rb +92 -0
- data/lib/k_domain/schemas/domain/old/related_entity.rb +36 -0
- data/lib/k_domain/schemas/domain/old/statistics.rb +21 -0
- data/lib/k_domain/schemas/domain/old/validate.rb +25 -0
- data/lib/k_domain/schemas/domain/old/validates.rb +50 -0
- data/lib/k_domain/schemas/domain_model.rb +14 -0
- data/lib/k_domain/schemas/investigate.rb +15 -0
- data/lib/k_domain/schemas/rails_resource.rb +16 -0
- data/lib/k_domain/version.rb +1 -1
- data/lib/k_domain.rb +22 -1
- data/templates/load_schema.rb +226 -0
- metadata +91 -2
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module DomainModel
|
5
|
+
class HasOne
|
6
|
+
# KEYS = [:model_name, :model_name_plural, :a_lambda, :class_name, :foreign_key, :primary_key, :infer_key]
|
7
|
+
KEYS = %i[a_lambda class_name foreign_key primary_key infer_key code_duplicate].freeze
|
8
|
+
|
9
|
+
attr_accessor :name
|
10
|
+
|
11
|
+
attr_accessor :model_name
|
12
|
+
attr_accessor :model_name_plural
|
13
|
+
|
14
|
+
attr_accessor :a_lambda
|
15
|
+
attr_accessor :class_name
|
16
|
+
attr_accessor :foreign_key
|
17
|
+
attr_accessor :primary_key
|
18
|
+
|
19
|
+
def infer_key
|
20
|
+
primary_key.nil? ? "#{name}_id" : primary_key
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :related_entity
|
24
|
+
attr_accessor :code_duplicate
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
{
|
28
|
+
name: name,
|
29
|
+
model_name: model_name,
|
30
|
+
model_name_plural: model_name_plural,
|
31
|
+
a_lambda: a_lambda,
|
32
|
+
class_name: class_name,
|
33
|
+
foreign_key: foreign_key,
|
34
|
+
primary_key: primary_key,
|
35
|
+
code_duplicate: code_duplicate,
|
36
|
+
related_entity: related_entity.to_h
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module DomainModel
|
5
|
+
# Rails model represents information that is found the model.rb class in the rails project
|
6
|
+
class RailsModel
|
7
|
+
attr_accessor :name
|
8
|
+
attr_accessor :name_plural
|
9
|
+
attr_accessor :name_original
|
10
|
+
attr_accessor :documentation_rel_path
|
11
|
+
attr_accessor :model_path
|
12
|
+
|
13
|
+
# @param [Symbol] value The value of ID has different meanings
|
14
|
+
# @option value :true Id column exists and it uses an Integer type
|
15
|
+
# @option value :false Id column does not exist
|
16
|
+
# @option value :bigserial Id column exists and it uses a BigSerial type
|
17
|
+
attr_accessor :id
|
18
|
+
|
19
|
+
attr_accessor :force
|
20
|
+
attr_accessor :primary_key
|
21
|
+
attr_accessor :quirks
|
22
|
+
|
23
|
+
attr_accessor :ruby_raw
|
24
|
+
attr_accessor :ruby_code
|
25
|
+
attr_accessor :ruby_frozen
|
26
|
+
attr_accessor :ruby_header
|
27
|
+
attr_accessor :ruby_code_public
|
28
|
+
attr_accessor :ruby_code_private
|
29
|
+
|
30
|
+
attr_accessor :default_scope
|
31
|
+
attr_accessor :scopes
|
32
|
+
attr_accessor :public_class_methods
|
33
|
+
attr_accessor :public_instance_methods
|
34
|
+
attr_accessor :private_instance_methods
|
35
|
+
|
36
|
+
# stats
|
37
|
+
attr_accessor :time_stamp1
|
38
|
+
attr_accessor :time_stamp2
|
39
|
+
attr_accessor :time_stamp3
|
40
|
+
|
41
|
+
def code_length
|
42
|
+
ruby_raw&.length
|
43
|
+
end
|
44
|
+
|
45
|
+
def display_quirks
|
46
|
+
quirks.join(' ')
|
47
|
+
end
|
48
|
+
|
49
|
+
def exists?
|
50
|
+
File.exist?(model_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
@quirks = []
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_quirk(quirk)
|
58
|
+
@quirks << quirk
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_h
|
62
|
+
{
|
63
|
+
name: name,
|
64
|
+
name_plural: name_plural,
|
65
|
+
name_original: name_original,
|
66
|
+
documentation_rel_path: documentation_rel_path,
|
67
|
+
model_path: model_path,
|
68
|
+
id: id,
|
69
|
+
force: force,
|
70
|
+
primary_key: primary_key,
|
71
|
+
quirks: quirks,
|
72
|
+
ruby_raw: ruby_raw,
|
73
|
+
ruby_code: ruby_code,
|
74
|
+
ruby_frozen: ruby_frozen,
|
75
|
+
ruby_header: ruby_header,
|
76
|
+
ruby_code_public: ruby_code_public,
|
77
|
+
ruby_code_private: ruby_code_private,
|
78
|
+
default_scope: default_scope,
|
79
|
+
scopes: scopes,
|
80
|
+
public_class_methods: public_class_methods,
|
81
|
+
public_instance_methods: public_instance_methods,
|
82
|
+
private_instance_methods: private_instance_methods,
|
83
|
+
time_stamp1: time_stamp1,
|
84
|
+
time_stamp2: time_stamp2,
|
85
|
+
time_stamp3: time_stamp3,
|
86
|
+
code_length: code_length,
|
87
|
+
exists: exists?
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module DomainModel
|
5
|
+
class RelatedEntity
|
6
|
+
# Name of the entity model
|
7
|
+
attr_accessor :name
|
8
|
+
attr_accessor :name_plural
|
9
|
+
attr_accessor :main_key
|
10
|
+
|
11
|
+
attr_accessor :trait1
|
12
|
+
attr_accessor :trait2
|
13
|
+
attr_accessor :trait3
|
14
|
+
|
15
|
+
def initialize(entity)
|
16
|
+
@name = entity.name
|
17
|
+
@name_plural = entity.name_plural
|
18
|
+
@main_key = entity.main_key
|
19
|
+
@trait1 = entity.trait1
|
20
|
+
@trait2 = entity.trait2
|
21
|
+
@trait3 = entity.trait3
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
{
|
26
|
+
name: name,
|
27
|
+
name_plural: name_plural,
|
28
|
+
main_key: main_key,
|
29
|
+
trait1: trait1,
|
30
|
+
trait2: trait2,
|
31
|
+
trait3: trait3
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# module KDomain
|
3
|
+
# module DomainModel
|
4
|
+
# # Rails model represents information that is found the model.rb class in the rails project
|
5
|
+
# class Statistics
|
6
|
+
# attr_accessor :column_counts
|
7
|
+
# attr_accessor :code_counts
|
8
|
+
# attr_accessor :code_dsl_counts
|
9
|
+
# attr_accessor :data_counts
|
10
|
+
# attr_accessor :issues
|
11
|
+
|
12
|
+
# def initialize(meta)
|
13
|
+
# @column_counts = OpenStruct.new(meta[:column_counts])
|
14
|
+
# @code_counts = OpenStruct.new(meta[:code_counts])
|
15
|
+
# @code_dsl_counts = OpenStruct.new(meta[:code_dsl_counts])
|
16
|
+
# @data_counts = OpenStruct.new(meta[:data_counts])
|
17
|
+
# @issues = meta[:issues]
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module DomainModel
|
5
|
+
class Validate
|
6
|
+
KEYS = [:on].freeze
|
7
|
+
|
8
|
+
attr_accessor :methods
|
9
|
+
|
10
|
+
attr_accessor :on
|
11
|
+
|
12
|
+
def format_on
|
13
|
+
for_template(on)
|
14
|
+
end
|
15
|
+
|
16
|
+
def for_template(value)
|
17
|
+
return nil if value.nil?
|
18
|
+
return value.to_s if value.is_a?(Hash)
|
19
|
+
return ":#{value}" if value.is_a?(Symbol)
|
20
|
+
|
21
|
+
value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KDomain
|
4
|
+
module DomainModel
|
5
|
+
class Validates
|
6
|
+
KEYS = %i[length unless format presence].freeze
|
7
|
+
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
attr_accessor :length
|
11
|
+
attr_accessor :unless
|
12
|
+
attr_accessor :format
|
13
|
+
attr_accessor :presence
|
14
|
+
|
15
|
+
def format_length
|
16
|
+
for_template(length)
|
17
|
+
end
|
18
|
+
|
19
|
+
def format_unless
|
20
|
+
for_template(self.unless)
|
21
|
+
end
|
22
|
+
|
23
|
+
def format_format
|
24
|
+
for_template(self.format)
|
25
|
+
end
|
26
|
+
|
27
|
+
def format_presence
|
28
|
+
for_template(presence)
|
29
|
+
end
|
30
|
+
|
31
|
+
def for_template(value)
|
32
|
+
return nil if value.nil?
|
33
|
+
return value.to_s if value.is_a?(Hash)
|
34
|
+
return ":#{value}" if value.is_a?(Symbol)
|
35
|
+
|
36
|
+
value
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_h
|
40
|
+
{
|
41
|
+
name: name,
|
42
|
+
length: length,
|
43
|
+
unless: self.unless,
|
44
|
+
format: self.format,
|
45
|
+
presence: presence
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# DomainModel holds the entire domain model including database and ancillary information
|
4
|
+
module KDomain
|
5
|
+
module Schemas
|
6
|
+
class DomainModel < Dry::Struct
|
7
|
+
attribute :domain , KDomain::DomainModel::Domain
|
8
|
+
attribute :database , KDomain::Database::Schema
|
9
|
+
attribute :dictionary , KDomain::Schemas::Dictionary
|
10
|
+
attribute :rails_resource , KDomain::Schemas::RailsResource
|
11
|
+
attribute :investigate , KDomain::Schemas::Investigate
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Domain class holds a dictionary entry
|
4
|
+
module KDomain
|
5
|
+
module Schemas
|
6
|
+
class Investigate < Dry::Struct
|
7
|
+
attribute :issues , Types::Strict::Array do
|
8
|
+
attribute :step , Types::Strict::String
|
9
|
+
attribute :location , Types::Strict::String
|
10
|
+
attribute :key , Types::Strict::String.optional.default(nil)
|
11
|
+
attribute :message , Types::Strict::String
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Domain class holds a dictionary entry
|
4
|
+
module KDomain
|
5
|
+
module Schemas
|
6
|
+
class RailsResource < Dry::Struct
|
7
|
+
attribute :models , Types::Strict::Array do
|
8
|
+
attribute :model_name , Types::Strict::String
|
9
|
+
attribute :table_name , Types::Strict::String
|
10
|
+
attribute :file , Types::Strict::String
|
11
|
+
attribute :exist , Types::Strict::Bool
|
12
|
+
attribute :state , Types::Strict::String
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/k_domain/version.rb
CHANGED
data/lib/k_domain.rb
CHANGED
@@ -1,14 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
require 'dry-struct'
|
3
5
|
require 'k_log'
|
6
|
+
require 'peeky'
|
4
7
|
require 'k_domain/version'
|
8
|
+
require 'k_domain/schemas/_'
|
9
|
+
require 'k_domain/raw_db_schema/transform'
|
10
|
+
require 'k_domain/raw_db_schema/load'
|
11
|
+
require 'k_domain/domain_model/transform'
|
12
|
+
require 'k_domain/domain_model/transform_steps/_'
|
13
|
+
require 'k_domain/domain_model/load'
|
5
14
|
|
6
|
-
|
15
|
+
# # This is useful if you want to initialize structures via Hash
|
16
|
+
# class SymbolizeStruct < Dry::Struct
|
17
|
+
# transform_keys(&:to_sym)
|
18
|
+
# end
|
7
19
|
|
8
20
|
module KDomain
|
9
21
|
# raise KDomain::Error, 'Sample message'
|
10
22
|
class Error < StandardError; end
|
11
23
|
|
24
|
+
module Gem
|
25
|
+
def self.root
|
26
|
+
File.expand_path('..', File.dirname(__FILE__))
|
27
|
+
end
|
28
|
+
def self.resource(resource_path)
|
29
|
+
File.join(root, resource_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
12
33
|
# Your code goes here...
|
13
34
|
end
|
14
35
|
|
@@ -0,0 +1,226 @@
|
|
1
|
+
class LoadSchema
|
2
|
+
attr_reader :schema
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@unique_keys = {}
|
6
|
+
@current_table = nil
|
7
|
+
@rails_version = 4
|
8
|
+
@schema = {
|
9
|
+
tables: [],
|
10
|
+
foreign_keys: [],
|
11
|
+
indexes: [],
|
12
|
+
meta: {
|
13
|
+
rails: @rails_version,
|
14
|
+
db_info: {
|
15
|
+
type: 'postgres',
|
16
|
+
version: nil, # TODO
|
17
|
+
extensions: []
|
18
|
+
},
|
19
|
+
unique_keys: []
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
# ----------------------------------------------------------------------
|
25
|
+
# Inject start
|
26
|
+
# original file: {{source_file}}
|
27
|
+
# ----------------------------------------------------------------------
|
28
|
+
def load_schema
|
29
|
+
{{rails_schema}}
|
30
|
+
end
|
31
|
+
|
32
|
+
# ----------------------------------------------------------------------
|
33
|
+
# original file: {{source_file}}
|
34
|
+
# Inject end
|
35
|
+
# ----------------------------------------------------------------------
|
36
|
+
|
37
|
+
def write_json(file)
|
38
|
+
schema[:meta][:rails] = @rails_version
|
39
|
+
File.write(file, JSON.pretty_generate(schema))
|
40
|
+
end
|
41
|
+
|
42
|
+
# This is the rails timestamp and will be replaced by the action rails version
|
43
|
+
def load(version:)
|
44
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
45
|
+
# puts 'about to load'
|
46
|
+
yield if block_given?
|
47
|
+
|
48
|
+
schema[:meta][:rails] = @rails_version
|
49
|
+
|
50
|
+
sort
|
51
|
+
# code to time
|
52
|
+
|
53
|
+
# log.kv 'extensions', schema[:db_info][:extensions].length
|
54
|
+
# log.kv 'tables', schema[:tables].length
|
55
|
+
# log.kv 'indexes', schema[:indexes].length
|
56
|
+
# # a low foreign_keys count is indicative of not using SQL referential integrity
|
57
|
+
# log.kv 'foreign_keys', schema[:foreign_keys].length
|
58
|
+
# log.kv 'Time Taken', (finish - start)
|
59
|
+
|
60
|
+
# puts schema[:db_info][:extensions]
|
61
|
+
# print_unique_keys(type: :foreign_keys, title: 'unique options for foreign_keys')
|
62
|
+
# print_unique_keys(type: :columns, title: 'unique options for columns')
|
63
|
+
# print_unique_keys(type: :fields, category: :integer , title: 'unique options for column - integer')
|
64
|
+
# print_unique_keys(type: :fields, category: :decimal , title: 'unique options for column - decimal')
|
65
|
+
# print_unique_keys(type: :fields, category: :string , title: 'unique options for column - string')
|
66
|
+
# print_unique_keys(type: :fields, category: :datetime, title: 'unique options for column - datetime')
|
67
|
+
# print_unique_keys(type: :fields, category: :date , title: 'unique options for column - date')
|
68
|
+
# print_unique_keys(type: :fields, category: :text , title: 'unique options for column - text')
|
69
|
+
# print_unique_keys(type: :fields, category: :boolean , title: 'unique options for column - boolean')
|
70
|
+
# print_unique_keys(type: :fields, category: :jsonb , title: 'unique options for column - jsonb')
|
71
|
+
# print_unique_keys(type: :fields, category: :hstore , title: 'unique options for column - hstore')
|
72
|
+
# print_unique_keys(type: :fields, category: :float , title: 'unique options for column - float')
|
73
|
+
end
|
74
|
+
|
75
|
+
def enable_extension(name)
|
76
|
+
# puts "enable_extension(#{name})"
|
77
|
+
schema[:meta][:db_info][:extensions] << name
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_table(name, **opts)
|
81
|
+
id = opts[:id]
|
82
|
+
primary_key = opts[:primary_key] || (id == false ? nil : "id")
|
83
|
+
primary_key_type = if id == false
|
84
|
+
nil
|
85
|
+
elsif id.nil?
|
86
|
+
"bigint"
|
87
|
+
else
|
88
|
+
id
|
89
|
+
end
|
90
|
+
|
91
|
+
@current_table = {
|
92
|
+
name: name,
|
93
|
+
primary_key: primary_key, # infer the actual value that should be in the database
|
94
|
+
primary_key_type: primary_key_type, # infer the actual value that should be in the database
|
95
|
+
columns: [],
|
96
|
+
indexes: [],
|
97
|
+
rails_schema: { # as reported by the rails schema
|
98
|
+
primary_key: opts[:primary_key],
|
99
|
+
id: id,
|
100
|
+
force: opts[:force]
|
101
|
+
}
|
102
|
+
}
|
103
|
+
# schema[:tables][name] = @current_table
|
104
|
+
schema[:tables] << @current_table
|
105
|
+
|
106
|
+
yield(self) if block_given?
|
107
|
+
end
|
108
|
+
|
109
|
+
def add_field(name, type, **opts)
|
110
|
+
# puts "add_field(#{name}, #{type})"
|
111
|
+
row = { name: name, type: type, **opts }
|
112
|
+
@current_table[:columns] << row
|
113
|
+
|
114
|
+
add_unique_keys(row.keys, type: :columns)
|
115
|
+
add_unique_keys(row.keys, type: :fields, category: type)
|
116
|
+
end
|
117
|
+
|
118
|
+
def add_index(name, fields, **opts)
|
119
|
+
# puts "add_index(#{name})"
|
120
|
+
row = { name: name, fields: fields, **opts }
|
121
|
+
@current_table[:indexes] << row
|
122
|
+
schema[:indexes] << row
|
123
|
+
add_unique_keys(row.keys, type: :indexes)
|
124
|
+
end
|
125
|
+
|
126
|
+
# This method was introduced onto the schema in rails 5
|
127
|
+
def index(fields, **opts)
|
128
|
+
@rails_version = 5
|
129
|
+
name = opts[:name]
|
130
|
+
opts.delete(:name)
|
131
|
+
add_index(name, fields, **opts)
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
def add_foreign_key(left_table, right_table, **opts)
|
136
|
+
# puts "add_foreign_key(#{left_table}, #{right_table})"
|
137
|
+
row = { left: left_table, right: right_table, **opts }
|
138
|
+
schema[:foreign_keys] << row
|
139
|
+
add_unique_keys(row.keys, type: :foreign_keys)
|
140
|
+
end
|
141
|
+
|
142
|
+
def add_unique_keys(keys, type:, category: nil)
|
143
|
+
key = [type, category, keys.join('-')].compact.join('|')
|
144
|
+
return if @unique_keys.key?(key)
|
145
|
+
|
146
|
+
@unique_keys[key] = key
|
147
|
+
schema[:meta][:unique_keys] << { type: type, category: category, key: keys.join(','), keys: keys }
|
148
|
+
end
|
149
|
+
|
150
|
+
def print_unique_keys(type:, category: nil, title: )
|
151
|
+
log.section_heading(title)
|
152
|
+
|
153
|
+
filter_key_infos = schema[:meta][:unique_keys].select { |key_info| key_info[:type] == type && (category.nil? || key_info[:category] == category) }
|
154
|
+
|
155
|
+
# log.kv 'all', filter_key_infos.flat_map { |key_info| key_info[:keys] }.uniq, 50
|
156
|
+
|
157
|
+
filter_key_infos.each do |key_info|
|
158
|
+
log.kv key_info[:key], key_info[:keys], 50
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def integer(name, **opts)
|
163
|
+
add_field(name, :integer, **opts)
|
164
|
+
end
|
165
|
+
|
166
|
+
def bigint(name, **opts)
|
167
|
+
add_field(name, :bigint, **opts)
|
168
|
+
end
|
169
|
+
|
170
|
+
def decimal(name, **opts)
|
171
|
+
add_field(name, :decimal, **opts)
|
172
|
+
end
|
173
|
+
|
174
|
+
def string(name, **opts)
|
175
|
+
add_field(name, :string, **opts)
|
176
|
+
end
|
177
|
+
|
178
|
+
def datetime(name, **opts)
|
179
|
+
add_field(name, :datetime, **opts)
|
180
|
+
end
|
181
|
+
|
182
|
+
def date(name, **opts)
|
183
|
+
add_field(name, :date, **opts)
|
184
|
+
end
|
185
|
+
|
186
|
+
def text(name, **opts)
|
187
|
+
add_field(name, :text, **opts)
|
188
|
+
end
|
189
|
+
|
190
|
+
def boolean(name, **opts)
|
191
|
+
add_field(name, :boolean, **opts)
|
192
|
+
end
|
193
|
+
|
194
|
+
def jsonb(name, **opts)
|
195
|
+
add_field(name, :jsonb, **opts)
|
196
|
+
end
|
197
|
+
|
198
|
+
def hstore(name, **opts)
|
199
|
+
add_field(name, :hstore, **opts)
|
200
|
+
end
|
201
|
+
|
202
|
+
def float(name, **opts)
|
203
|
+
add_field(name, :float, **opts)
|
204
|
+
end
|
205
|
+
|
206
|
+
def sort
|
207
|
+
schema[:indexes].sort_by! { |i| i[:name] }
|
208
|
+
schema[:tables].each { |table| table[:indexes].sort_by! { |i| i[:name] } }
|
209
|
+
|
210
|
+
# Insert a key that represents all unique keys, and then sort
|
211
|
+
unique_keys_per_group = schema[:meta][:unique_keys]
|
212
|
+
.group_by { |key_info| [key_info[:type], key_info[:category]] }
|
213
|
+
.map do |group, values|
|
214
|
+
all_keys = values.flat_map { |key_info| key_info[:keys] }.uniq
|
215
|
+
{
|
216
|
+
type: group[0],
|
217
|
+
category: group[01],
|
218
|
+
key: 'all',
|
219
|
+
keys: all_keys
|
220
|
+
}
|
221
|
+
end
|
222
|
+
|
223
|
+
schema[:meta][:unique_keys].concat(unique_keys_per_group)
|
224
|
+
schema[:meta][:unique_keys].sort! { |a,b| ([a[:type], a[:category],a[:key]] <=> [b[:type], b[:category],b[:key]]) }
|
225
|
+
end
|
226
|
+
end
|