lib/pgslice.rb in pgslice-0.1.4 vs lib/pgslice.rb in pgslice-0.1.5

- old
+ new

@@ -1,9 +1,8 @@ require "pgslice/version" require "slop" require "pg" -require "active_support/all" module PgSlice class Error < StandardError; end class Client @@ -115,25 +114,26 @@ range = (-1 * past)..future # ensure table has trigger abort "No trigger on table: #{table}\nDid you mean to use --intermediate?" unless has_trigger?(trigger_name, table) - period, field, name_format, inc, today = settings_from_table(original_table, table) + index_defs = execute("select pg_get_indexdef(indexrelid) from pg_index where indrelid = $1::regclass AND indisprimary = 'f'", [original_table]).map { |r| r["pg_get_indexdef"] } + primary_key = self.primary_key(table) - days = range.map { |n| today + (n * inc) } queries = [] - index_defs = execute("select pg_get_indexdef(indexrelid) from pg_index where indrelid = $1::regclass AND indisprimary = 'f'", [original_table]).map { |r| r["pg_get_indexdef"] } - primary_key = self.primary_key(table) + period, field = settings_from_table(original_table, table) + today = round_date(Date.today, period) + range.each do |n| + day = advance_date(today, period, n) - days.each do |day| - partition_name = "#{original_table}_#{day.strftime(name_format)}" + partition_name = "#{original_table}_#{day.strftime(name_format(period))}" next if table_exists?(partition_name) queries << <<-SQL CREATE TABLE #{partition_name} - (CHECK (#{field} >= #{sql_date(day)} AND #{field} < #{sql_date(day + inc)})) + (CHECK (#{field} >= #{sql_date(day)} AND #{field} < #{sql_date(advance_date(day, period, 1))})) INHERITS (#{table}); SQL queries << "ALTER TABLE #{partition_name} ADD PRIMARY KEY (#{primary_key});" if primary_key @@ -159,15 +159,16 @@ end abort "Table not found: #{source_table}" unless table_exists?(source_table) abort "Table not found: #{dest_table}" unless table_exists?(dest_table) - period, field, name_format, inc, today = settings_from_table(table, dest_table) + period, field = settings_from_table(table, dest_table) + name_format = self.name_format(period) existing_tables = self.existing_tables(like: "#{table}_%").select { |t| /#{Regexp.escape("#{table}_")}(\d{4,6})/.match(t) }.sort - starting_time = DateTime.strptime(existing_tables.first.last(8), name_format) - ending_time = DateTime.strptime(existing_tables.last.last(8), name_format) + inc + starting_time = DateTime.strptime(existing_tables.first.split("_").last, name_format) + ending_time = advance_date(DateTime.strptime(existing_tables.last.split("_").last, name_format), period, 1) primary_key = self.primary_key(table) max_source_id = max_id(source_table, primary_key) max_dest_id = if options[:swapped] @@ -410,29 +411,45 @@ def sql_date(time) "'#{time.strftime("%Y-%m-%d")}'::date" end + def name_format(period) + case period.to_sym + when :day + "%Y%m%d" + else + "%Y%m" + end + end + + def round_date(date, period) + date = date.to_date + case period.to_sym + when :day + date + else + Date.new(date.year, date.month) + end + end + + def advance_date(date, period, count = 1) + date = date.to_date + case period.to_sym + when :day + date.next_day(count) + else + date.next_month(count) + end + end + def settings_from_table(original_table, table) trigger_name = self.trigger_name(original_table) function_def = execute("select pg_get_functiondef(oid) from pg_proc where proname = $1", [trigger_name])[0]["pg_get_functiondef"] sql_format = SQL_FORMAT.find { |_, f| function_def.include?("'#{f}'") } abort "Could not read settings" unless sql_format period = sql_format[0] field = /to_char\(NEW\.(\w+),/.match(function_def)[1] - - today = Time.now - case period - when :day - name_format = "%Y%m%d" - inc = 1.day - today = today.beginning_of_day - else - name_format = "%Y%m" - inc = 1.month - today = today.beginning_of_month - end - - [period, field, name_format, inc, today] + [period, field] end end end