mariadb_temporal_tables 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 34791f0627df25bcf1364112a1199a331fc19a2c195d7d7db16212338d77d3b1
4
- data.tar.gz: ce80c2c4bee5e4135e3bb7f0ae39d465b033932450be4d29cd013bf37f22f43e
3
+ metadata.gz: c1e568e3267a15a75752db985165b1707ea771dfed1501dacf95b5560ffdf1aa
4
+ data.tar.gz: e3b25c22dcc408ab54ccfd0835f4ea3bf78824c11173bc07fa0cec668be349c6
5
5
  SHA512:
6
- metadata.gz: 8cd6e6dafadde098a35a0cc68ca590afbaea7e4e9a45858016b73bc040c06caa979380067098322da35cb621824aff32adbb27dfbf193fc21eb3099cef16fdc8
7
- data.tar.gz: 65637454b429dc765af1500aab5a120371da205bf463eb9af4daace888bfb5af7d5416ca50db60684ead5cbbe76facb879f59478b1747360a2c1c239ae2e499b
6
+ metadata.gz: de4e1cdb8a056a3d544a3f5f523f4b157c140d85a194fb96951a7c3046da4fb57dcc4b256981cae09480cacde75638f8d569d710ac877269e7748b6f52c00a9c
7
+ data.tar.gz: ab3b4704b53e7236a0c1ed81a9551daa6c31544f17b28a03d7dda84955006f3ae82e9e5301660dfae0f535f6f9b701a8e746442d9ef30d8dfb43752f04a78e96
@@ -0,0 +1,101 @@
1
+ require "active_support/concern"
2
+
3
+ module MariaDBTemporalTables
4
+
5
+ # <tt>ActiveSupport::Concern</tt> that adds methods to the associated model that utilize MariaDB application-time periods
6
+ #
7
+ # <tt>application_versioning_options</tt> can be called in the model to set options for this concern
8
+ # See ApplicationVersioning#application_versioning_options
9
+ module ApplicationVersioning
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ application_versioning_options # Initialize with default options
14
+ end
15
+
16
+ class_methods do
17
+ attr_reader :application_versioning_start_column_name, :application_versioning_end_column_name
18
+
19
+ # Sets options for application versioning
20
+ # @param [Hash] options the options to use for application versioning
21
+ # @option options [String] :start_column_name the name of the column that indicates start of validity of application versioning
22
+ # @option options [String] :end_column_name the name of the column that indicates end of validity of application versioning
23
+ # @option options [Symbol, Array<Symbol>] :primary_key primary key to be set as the model primary key (can be single or composite key)
24
+ def application_versioning_options(options = {})
25
+ @application_versioning_start_column_name = options[:start_column_name] || "valid_start"
26
+ @application_versioning_end_column_name = options[:end_column_name] || "valid_end"
27
+
28
+ self.primary_key = options[:primary_key] || [:id, @application_versioning_end_column_name]
29
+ end
30
+
31
+ # Gets all records that were valid at the given time
32
+ # @param [Time, DateTime, Date, String] valid_at used to get records valid at this time
33
+ def all_valid_at(valid_at)
34
+ parsed_date = parse_date_or_time(valid_at)
35
+ query = "SELECT * FROM #{table_name} WHERE ? BETWEEN #{@application_versioning_start_column_name} AND #{@application_versioning_end_column_name}"
36
+ return find_by_sql [query, parsed_date]
37
+ end
38
+
39
+ # Gets all records that were valid at the given time ordered by the given order attributes
40
+ # @param [Time, DateTime, Date, String] valid_at used to get records valid at this time
41
+ # @param [String] order order to be used on the SQL query ("ASC" or "DESC")
42
+ # @param [Array<String>, Array<Symbol>] order_attributes list of attributes to order by
43
+ # @return [Array<ActiveRecord::Base>] array of active record objects of the current model ordered
44
+ def order_valid_at(valid_at, order = "ASC", *order_attributes)
45
+ parsed_date = parse_date_or_time(valid_at)
46
+ order_attributes_s = order_attributes.join(", ")
47
+ query = "SELECT * FROM #{table_name} WHERE ? BETWEEN #{@application_versioning_start_column_name} AND #{@application_versioning_end_column_name} ORDER BY #{order_attributes_s} #{order}"
48
+ return find_by_sql [query, parsed_date]
49
+ end
50
+
51
+ # Gets all records that were valid at the given time filtered by the given where attributes
52
+ # @param [Time, DateTime, Date, String] valid_at used to get records valid at this time
53
+ # @param [Hash] where_attributes key-value hash to be used to generate where clause (where key='value' for each)
54
+ # @return [Array<ActiveRecord::Base>] array of active record objects of the current model filtered by attributes
55
+ def where_valid_at(valid_at, where_attributes)
56
+ parsed_date = parse_date_or_time(valid_at)
57
+
58
+ where_attributes_s = "WHERE "
59
+ first = true
60
+
61
+ where_attributes.each do |attr|
62
+ unless first
63
+ where_attributes_s += " AND "
64
+ end
65
+ first = false
66
+
67
+ where_attributes_s += "#{attr[0]} = '#{attr[1]}'"
68
+ end
69
+
70
+ query = "SELECT * FROM #{table_name} #{where_attributes_s} AND ? BETWEEN #{@application_versioning_start_column_name} AND #{@application_versioning_end_column_name}"
71
+ return find_by_sql [query, parsed_date]
72
+ end
73
+
74
+ def parse_date_or_time(date_or_time)
75
+ column_type = columns_hash[@application_versioning_end_column_name].type
76
+
77
+ case column_type
78
+ when :datetime
79
+ if date_or_time.is_a? DateTime
80
+ return date_or_time
81
+ end
82
+
83
+ return DateTime.parse(date_or_time)
84
+ when :timestamp
85
+ if date_or_time.is_a? Time
86
+ return date_or_time
87
+ end
88
+
89
+ return Time.parse(date_or_time)
90
+ else
91
+ if date_or_time.is_a? Date
92
+ return date_or_time
93
+ end
94
+
95
+ return Date.parse(date_or_time)
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,41 @@
1
+ require "active_support/concern"
2
+
3
+ module MariaDBTemporalTables
4
+
5
+ # <tt>ActiveSupport::Concern</tt> that combines the utility of SystemVersioning and ApplicationVersioning
6
+ #
7
+ # <tt>system_versioning_options</tt> and <tt>application_versioning_options</tt> can be called in the model to set options for this concern
8
+ module CombinedVersioning
9
+ extend ActiveSupport::Concern
10
+ include SystemVersioning
11
+ include ApplicationVersioning
12
+
13
+
14
+ class_methods do
15
+
16
+ # Gets all record as of time (system versioning) and valid at time (application versioning)
17
+ # @param [Time, DateTime, Date, String] valid_at used to get records valid at this time
18
+ # @param [Time, String] as_of_time used to get records as of this time
19
+ def all_valid_at_as_of(valid_at, as_of_time)
20
+ parsed_time = parse_time(as_of_time)
21
+ parsed_date = parse_date_or_time(valid_at)
22
+ query = "SELECT * FROM #{table_name} FOR SYSTEM_TIME AS OF TIMESTAMP? WHERE ? BETWEEN #{application_versioning_start_column_name} AND #{application_versioning_end_column_name}"
23
+ return find_by_sql [query, parsed_time, parsed_date]
24
+ end
25
+
26
+ # Gets all record as of time (system versioning) and valid at time (application versioning) ordered by the given order attributes
27
+ # @param [Time, DateTime, Date, String] valid_at used to get records valid at this time
28
+ # @param [Time, String] as_of_time used to get records as of this time
29
+ # @param [Array<String>, Array<Symbol>] order_attributes list of attributes to order by
30
+ # @return [Array<ActiveRecord::Base>] array of active record objects of the current model ordered
31
+ def order_valid_at_as_of(valid_at, as_of_time, order="ASC", *order_attributes)
32
+ parsed_time = parse_time(as_of_time)
33
+ parsed_date = parse_date_or_time(valid_at)
34
+ order_attributes_s = order_attributes.join(", ")
35
+ query = "SELECT * FROM #{table_name} FOR SYSTEM_TIME AS OF TIMESTAMP? WHERE ? BETWEEN #{application_versioning_start_column_name} AND #{application_versioning_end_column_name} ORDER BY #{order_attributes_s} #{order}"
36
+ return find_by_sql [query, parsed_time, parsed_date]
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,212 @@
1
+ require "active_support/concern"
2
+
3
+ module MariaDBTemporalTables
4
+
5
+ # <tt>ActiveSupport::Concern</tt> that adds methods to the associated model that utilize MariaDB system versioning
6
+ #
7
+ # <tt>system_versioning_options</tt> can be called in the model to set options for this concern
8
+ # See SystemVersioning#system_versioning_options
9
+ module SystemVersioning
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ system_versioning_options # Initialize with default options
14
+ before_save :add_author, :add_change_list
15
+
16
+ # Get all the previous versions of this record, including the current version
17
+ # @param [String] order order to be used on the SQL query ("ASC" or "DESC")
18
+ # @return [Array<ActiveRecord::Base>] array of active record objects of the current model
19
+ def versions(order = "ASC")
20
+ where_clause = self.class.generate_where_clause_for_id(self.class.try(:primary_keys), self.id)
21
+ query = "SELECT * FROM #{self.class.table_name} FOR SYSTEM_TIME ALL #{where_clause} ORDER BY #{self.class.system_versioning_end_column_name} #{order}"
22
+ self.class.find_by_sql [query]
23
+ end
24
+
25
+ # Revert the current object to a specific version of an object with given id and at the time of end_value
26
+ # @param id [Integer, String, Array<String>] id of the object to revert to
27
+ # @param [Time, String] as_of_time time at which to revert to
28
+ # @return [Boolean] true when successful
29
+ def revert(id, as_of_time)
30
+ parsed_time = self.class.parse_time(as_of_time)
31
+ where_clause = self.class.generate_where_clause_for_id(self.class.try(:primary_keys), id)
32
+ query = "SELECT * FROM #{self.class.table_name} FOR SYSTEM_TIME AS OF TIMESTAMP? #{where_clause} LIMIT 1"
33
+ query_result = self.class.find_by_sql([query, parsed_time])
34
+
35
+ unless query_result
36
+ return false
37
+ end
38
+
39
+ revert_object = query_result[0]
40
+ attributes = revert_object.attributes.except(self.class.exclude_revert)
41
+ return self.update(attributes)
42
+ end
43
+
44
+ private
45
+
46
+ def add_author
47
+ if self.class.column_names.include? "author_id"
48
+ author = Thread.current[:mariadb_temporal_tables_current_author]
49
+ if author
50
+ self.author_id = author.id
51
+ else
52
+ Warning.warn("Could not find author to associate with version, make sure to call system_versioning_set_author in your controller")
53
+ end
54
+ end
55
+ end
56
+
57
+ def add_change_list
58
+ if self.class.column_names.include? "change_list"
59
+ change_list = get_change_list
60
+ self.change_list = change_list
61
+ end
62
+ end
63
+
64
+ def get_change_list
65
+ change_list = ""
66
+ self.changes.each do |attr_name, change|
67
+ if self.class.exclude_change_list.include? attr_name
68
+ next
69
+ end
70
+ change_text = ""
71
+ old_value = change[0]
72
+ new_value = change[1]
73
+
74
+ if is_nil_or_empty(old_value) && !is_nil_or_empty(new_value)
75
+ change_text = "Added #{attr_name}: #{new_value}"
76
+ elsif !is_nil_or_empty(old_value) && is_nil_or_empty(new_value)
77
+ change_text = "Removed #{attr_name}"
78
+ elsif !is_nil_or_empty(old_value) && !is_nil_or_empty(new_value) && old_value != new_value
79
+ change_text = "Updated #{attr_name}: #{old_value} -> #{new_value}"
80
+ else
81
+ next
82
+ end
83
+
84
+ change_list += change_text + "\n"
85
+ end
86
+ return change_list
87
+ end
88
+
89
+ def is_nil_or_empty(value)
90
+ if value.is_a? String
91
+ return value.nil? || value.empty?
92
+ end
93
+ return value.nil?
94
+ end
95
+ end
96
+
97
+ class_methods do
98
+ attr_reader :system_versioning_start_column_name, :system_versioning_end_column_name, :exclude_revert, :exclude_change_list
99
+
100
+ # Sets options for system versioning
101
+ # @param [Hash] options the options to use for system versioning
102
+ # @option options [String] :start_column_name the name of the column that indicates start of validity of system versioning
103
+ # @option options [String] :end_column_name the name of the column that indicates end of validity of system versioning
104
+ # @option options [Array<String>] :exclude_revert list of column names that should be excluded when reverting a record
105
+ # @option options [Array<String>] :exclude_change_list list of column names that should be excluded when generating the change list
106
+ # @option options [Symbol, Array<Symbol>] :primary_key primary key to be set as the model primary key (can be single or composite key)
107
+ def system_versioning_options(options = {})
108
+ @system_versioning_start_column_name = options[:start_column_name] || "transaction_start"
109
+ @system_versioning_end_column_name = options[:end_column_name] || "transaction_end"
110
+
111
+ default_exclude = %w[id author_id change_list]
112
+ @exclude_revert = (options[:exclude_revert] || []) + default_exclude + [@system_versioning_start_column_name, @system_versioning_end_column_name]
113
+ @exclude_change_list = (options[:exclude_change_list] || []) + default_exclude + [@system_versioning_start_column_name, @system_versioning_end_column_name]
114
+
115
+ self.primary_key = options[:primary_key] || :id
116
+ end
117
+
118
+ # Gets all records as of the given time
119
+ # @param [Time, String] as_of_time used to get records as of this time
120
+ def all_as_of(as_of_time)
121
+ parsed_time = parse_time(as_of_time)
122
+ query = "SELECT * FROM #{table_name} FOR SYSTEM_TIME AS OF TIMESTAMP?"
123
+ return find_by_sql [query, parsed_time]
124
+ end
125
+
126
+ # Gets all records as of the given time ordered by the given order attributes
127
+ # @param [Time, String] as_of_time used to get records as of this time
128
+ # @param [String] order order to be used on the SQL query ("ASC" or "DESC")
129
+ # @param [Array<String>, Array<Symbol>] order_attributes list of attributes to order by
130
+ # @return [Array<ActiveRecord::Base>] array of active record objects of the current model ordered
131
+ def order_as_of(as_of_time, order = "ASC", *order_attributes)
132
+ parsed_time = parse_time(as_of_time)
133
+ order_attributes_s = order_attributes.join(", ")
134
+ query = "SELECT * FROM #{table_name} FOR SYSTEM_TIME AS OF TIMESTAMP? ORDER BY #{order_attributes_s} #{order}"
135
+ return find_by_sql [query, parsed_time]
136
+ end
137
+
138
+ # Gets all records as of the given time filtered by the given where attributes
139
+ # @param [Time, String] as_of_time used to get records as of this time
140
+ # @param [Hash] where_attributes key-value hash to be used to generate where clause (where key='value' for each)
141
+ # @return [Array<ActiveRecord::Base>] array of active record objects of the current model filtered by attributes
142
+ def where_as_of(as_of_time, where_attributes)
143
+ parsed_time = parse_time(as_of_time)
144
+
145
+ where_attributes_s = "WHERE "
146
+ first = true
147
+
148
+ where_attributes.each do |attr|
149
+ unless first
150
+ where_attributes_s += " AND "
151
+ end
152
+ first = false
153
+
154
+ where_attributes_s += "#{attr[0]} = '#{attr[1]}'"
155
+ end
156
+
157
+ query = "SELECT * FROM #{table_name} FOR SYSTEM_TIME AS OF TIMESTAMP? #{where_attributes_s}"
158
+ return find_by_sql [query, parsed_time]
159
+ end
160
+
161
+ # Gets the single records as of the given time with the given id
162
+ # @param [Time, String] as_of_time used to get record as of this time
163
+ # @param [Integer, String, Array<String>] id id of the object to find
164
+ # @return [ActiveRecord::Base] active record object of the found object
165
+ def find_as_of(as_of_time, id)
166
+ parsed_time = parse_time(as_of_time)
167
+ where_clause = generate_where_clause_for_id(try(:primary_keys), id)
168
+ query = "SELECT * FROM #{table_name} FOR SYSTEM_TIME AS OF TIMESTAMP? #{where_clause} LIMIT 1"
169
+ return find_by_sql([query, parsed_time])[0]
170
+ end
171
+
172
+ # Gets the number of versions that an author has created. Any version where author_id is equal to the given id
173
+ # @param [Integer, String] author_id id of author
174
+ # @return [Integer] number of versions author has created
175
+ def versions_count_for_author(author_id)
176
+ query = "SELECT COUNT(*) AS count FROM #{table_name} FOR SYSTEM_TIME ALL WHERE author_id=?"
177
+ find_by_sql([query, author_id])[0].count
178
+ end
179
+
180
+ def parse_time(time)
181
+ if time.is_a? Time
182
+ return time
183
+ end
184
+
185
+ Time.parse(time)
186
+ end
187
+
188
+ # In case a composite key is used, this generates where clause considering composite keys
189
+ def generate_where_clause_for_id(primary_keys, id)
190
+ if primary_keys
191
+
192
+ unless id.is_a? Array # Composite id could be '1,other_key' or ["1","other_key"]
193
+ id = id.split(",")
194
+ end
195
+
196
+ where_clause = "WHERE "
197
+ (0...primary_keys.length).each do |i|
198
+ if i != 0
199
+ where_clause += " AND "
200
+ end
201
+ where_clause += "#{primary_keys[i]}='#{id[i]}'"
202
+ end
203
+ where_clause
204
+ else
205
+ "WHERE id = '#{id}'"
206
+ end
207
+ end
208
+
209
+ end
210
+
211
+ end
212
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails'
2
+
3
+ module MariaDBTemporalTables
4
+ class Railtie < Rails::Railtie
5
+ railtie_name :mariadb_temporal_tables
6
+
7
+ rake_tasks do
8
+ path = File.expand_path(__dir__)
9
+ Dir.glob("#{path}/../tasks/**/*.rake").each { |f| load f }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ require_relative "helpers/parser"
2
+ require_relative "helpers/migration_generator"
3
+
4
+ namespace :mariadb_temporal_tables do
5
+ include Parser
6
+
7
+ desc "Generates migration for adding application versioning to a table"
8
+ task :gen_migration_application do
9
+
10
+ options = parse_options("mariadb_temporal_tables:gen_migration_application")
11
+ table_name = options[:table_name]
12
+
13
+ if table_name.nil?
14
+ raise "Missing table parameter to create migration on. Use option --table=table_name to choose a table"
15
+ end
16
+
17
+ replace_primary_key = options[:replace_primary_key].nil? ? true : options[:replace_primary_key]
18
+ add_columns = options[:add_columns].nil? ? true : options[:add_columns]
19
+ column_type = options[:column_type] || "DATE"
20
+ start_column_name = options[:start_column_name] || "valid_start"
21
+ end_column_name = options[:end_column_name] || "valid_end"
22
+
23
+ unless %w[DATE TIMESTAMP DATETIME].include?(column_type)
24
+ raise "Unsupported column_type provided: #{column_type}"
25
+ end
26
+
27
+ migration_name = "add_application_versioning_to_#{table_name.downcase}"
28
+ puts "Generating migration #{migration_name}"
29
+
30
+ generator = MigrationGenerator.new
31
+ generator.generate_migration(migration_name,
32
+ "application_versioning.rb.erb",
33
+ { :replace_primary_key => replace_primary_key,
34
+ :add_columns => add_columns,
35
+ :column_type => column_type,
36
+ :start_column_name => start_column_name,
37
+ :end_column_name => end_column_name,
38
+ :table_name => table_name
39
+ })
40
+
41
+ puts "Migration generated successfully"
42
+ end
43
+
44
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "helpers/parser"
2
+ require_relative "helpers/migration_generator"
3
+
4
+ namespace :mariadb_temporal_tables do
5
+ include Parser
6
+
7
+ desc "Generates migration for adding system versioning to a table"
8
+ task :gen_migration_system do
9
+
10
+ options = parse_options("mariadb_temporal_tables:gen_migration_system")
11
+ table_name = options[:table_name]
12
+
13
+ if table_name.nil?
14
+ raise "Missing table parameter to create migration on. Use option --table=table_name to choose a table"
15
+ end
16
+
17
+ include_change_list = options[:include_change_list].nil? ? false : options[:include_change_list]
18
+ include_author_reference = options[:include_author_reference].nil? ? false : options[:include_author_reference]
19
+ author_table_name = options[:author_table_name] || "users"
20
+ start_column_name = options[:start_column_name] || "transaction_start"
21
+ end_column_name = options[:end_column_name] || "transaction_end"
22
+
23
+ migration_name = "add_system_versioning_to_#{table_name.downcase}"
24
+ puts "Generating migration #{migration_name}"
25
+
26
+ generator = MigrationGenerator.new
27
+ generator.generate_migration(migration_name,
28
+ "system_versioning.rb.erb",
29
+ { :include_change_list => include_change_list,
30
+ :include_author_reference => include_author_reference,
31
+ :author_table_name => author_table_name,
32
+ :start_column_name => start_column_name,
33
+ :end_column_name => end_column_name,
34
+ :table_name => table_name
35
+ })
36
+
37
+ puts "Migration generated successfully"
38
+ end
39
+
40
+ end
@@ -0,0 +1,38 @@
1
+ require "rails/generators"
2
+ require "rails/generators/active_record"
3
+
4
+ # Implementation based on how paper_trail gem achieves similar result
5
+ # https://github.com/paper-trail-gem/paper_trail/blob/master/lib/generators/paper_trail/migration_generator.rb
6
+ class MigrationGenerator < ::Rails::Generators::Base
7
+ include ::Rails::Generators::Migration
8
+
9
+ # Tells Migrations where to look for template files
10
+ source_root File.expand_path("../migration_templates", __dir__)
11
+
12
+ # Needs to be reimplemented or throws unimplemented error
13
+ def self.next_migration_number(dirname)
14
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
15
+ end
16
+
17
+ def generate_migration(migration_name, template_file, template_options)
18
+ migration_directory = File.expand_path("db/migrate")
19
+
20
+ if self.class.migration_exists?(migration_directory, migration_name)
21
+ raise "Can't generate migration #{migration_name} because it already exists."
22
+ end
23
+
24
+ @template_options = template_options
25
+ migration_template(template_file,
26
+ "db/migrate/#{migration_name}.rb",
27
+ {})
28
+ end
29
+
30
+ def migration_version
31
+ format(
32
+ "[%d.%d]",
33
+ ::ActiveRecord::VERSION::MAJOR,
34
+ ::ActiveRecord::VERSION::MINOR
35
+ )
36
+ end
37
+ end
38
+
@@ -0,0 +1,79 @@
1
+ require 'optparse'
2
+
3
+ # Usage of names arguments in Rake as shown here: http://www.mikeball.us/blog/rake-option-parser/
4
+ module Parser
5
+ def parse_options(command)
6
+ options = {}
7
+ option_parser = OptionParser.new
8
+ option_parser.banner = "Usage: rake #{command} [options]"
9
+
10
+ case command
11
+ when "mariadb_temporal_tables:gen_migration_application"
12
+ setup_parser_for_gen_migration_application(option_parser, options)
13
+ when "mariadb_temporal_tables:gen_migration_system"
14
+ setup_parser_for_gen_migration_system(option_parser, options)
15
+ else
16
+ raise "Unable to parse options for unknown command: #{command}"
17
+ end
18
+
19
+ args = option_parser.order!(ARGV) {}
20
+ option_parser.parse!(args)
21
+ options
22
+ end
23
+
24
+ private
25
+
26
+ def setup_parser_for_gen_migration_application(parser, options)
27
+ parser.on("--table=TABLE","Table to generate migration for") do |value|
28
+ options[:table_name] = value
29
+ end
30
+
31
+ parser.on("--add_columns=ADD","Whether columns should be added to table or not") do |value|
32
+ options[:add_columns] = value == "true"
33
+ end
34
+
35
+ parser.on("--start_column_name=NAME","Name of column that represents start of period") do |value|
36
+ options[:start_column_name] = value
37
+ end
38
+
39
+ parser.on("--end_column_name=NAME","Name of column that represents end of period") do |value|
40
+ options[:end_column_name] = value
41
+ end
42
+
43
+ parser.on("--replace_primary_key=REPLACE","Whether end column should be added to primary key or not") do |value|
44
+ options[:replace_primary_key] = value == "true"
45
+ end
46
+
47
+ parser.on("--column_type=TYPE","Type to use for column to be added") do |value|
48
+ options[:column_type] = value
49
+ end
50
+ end
51
+
52
+ def setup_parser_for_gen_migration_system(parser, options)
53
+ parser.on("--table=TABLE","Table to generate migration for") do |value|
54
+ options[:table_name] = value
55
+ end
56
+
57
+ parser.on("--include_change_list=INC","Whether change_list column should be added or not") do |value|
58
+ options[:include_change_list] = value == "true"
59
+ end
60
+
61
+ parser.on("--include_author_reference=INC","Whether reference of author id should be added or not") do |value|
62
+ options[:include_author_reference] = value == "true"
63
+ end
64
+
65
+ parser.on("--author_table=TABLE","Table to reference author id from") do |value|
66
+ options[:author_table_name] = value
67
+ end
68
+
69
+ parser.on("--start_column_name=NAME","Name of column that represents start of period") do |value|
70
+ options[:start_column_name] = value
71
+ end
72
+
73
+ parser.on("--end_column_name=NAME","Name of column that represents end of period") do |value|
74
+ options[:end_column_name] = value
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,16 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ execute <<-SQL
4
+ ALTER TABLE <%= @template_options[:table_name] %>
5
+ <%- if @template_options[:add_columns] -%>
6
+ ADD COLUMN <%= @template_options[:start_column_name] %> <%= @template_options[:column_type] %>,
7
+ ADD COLUMN <%= @template_options[:end_column_name] %> <%= @template_options[:column_type] %>,
8
+ <%- end -%>
9
+ ADD PERIOD FOR p(<%= @template_options[:start_column_name] %>,<%= @template_options[:end_column_name] %>),
10
+ <%- if @template_options[:replace_primary_key] -%>
11
+ DROP PRIMARY KEY,
12
+ ADD PRIMARY KEY(id, <%= @template_options[:end_column_name] %>)
13
+ <%- end -%>
14
+ SQL
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
+
3
+ def change
4
+ <%- if @template_options[:include_change_list] -%>
5
+ add_column :<%= @template_options[:table_name] %>, :change_list, :text
6
+ <%- end -%>
7
+ <%- if @template_options[:include_author_reference] -%>
8
+ add_column :<%= @template_options[:table_name] %>, :author_id, :bigint
9
+ add_foreign_key :<%= @template_options[:table_name] %>, :<%= @template_options[:author_table_name] %>, column: :author_id, primary_key: :id
10
+ <%- end -%>
11
+ execute <<-SQL
12
+ ALTER TABLE <%= @template_options[:table_name] %>
13
+ ADD COLUMN <%= @template_options[:start_column_name] %> TIMESTAMP(6) GENERATED ALWAYS AS ROW START,
14
+ ADD COLUMN <%= @template_options[:end_column_name] %> TIMESTAMP(6) GENERATED ALWAYS AS ROW END,
15
+ ADD PERIOD FOR SYSTEM_TIME(<%= @template_options[:start_column_name] %>, <%= @template_options[:end_column_name] %>),
16
+ ADD SYSTEM VERSIONING;
17
+ SQL
18
+ end
19
+
20
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mariadb_temporal_tables
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Youssef Henna
@@ -74,6 +74,16 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - lib/mariadb_temporal_tables.rb
77
+ - lib/mariadb_temporal_tables/concerns/application_versioning.rb
78
+ - lib/mariadb_temporal_tables/concerns/combined_versioning.rb
79
+ - lib/mariadb_temporal_tables/concerns/system_versioning.rb
80
+ - lib/mariadb_temporal_tables/railtie.rb
81
+ - lib/tasks/gen_migration_application.rake
82
+ - lib/tasks/gen_migration_system.rake
83
+ - lib/tasks/helpers/migration_generator.rb
84
+ - lib/tasks/helpers/parser.rb
85
+ - lib/tasks/migration_templates/application_versioning.rb.erb
86
+ - lib/tasks/migration_templates/system_versioning.rb.erb
77
87
  homepage: https://github.com/YoussefHenna/mariadb_temporal_tables
78
88
  licenses:
79
89
  - MIT