#!/usr/bin/ruby # encoding: utf-8 #Arunas Junevicius #2012-05-15 #Version : 1 #Kolmisoft require 'rubygems' require 'active_record' require 'optparse' require 'digest/sha1' options = {} optparse = OptionParser.new do|opts| # Define the options, and what they do options[:name] = nil opts.on( '-n', '--name NAME', "Database name, default 'mor'" ) do|n| options[:name] = n end options[:user] = nil opts.on( '-u', '--user USER', "Database user, default 'mor'" ) do|u| options[:user] = u end options[:pasw] = nil opts.on( '-p', '--password PASSWORD', "Database password, default 'mor'" ) do|p| options[:pasw] = p end options[:host] = nil opts.on( '-s', '--server HOST', "Database host, default 'localhost'" ) do|h| options[:host] = h end options[:start] = nil opts.on( '-S', '--start DATETIME', "DATETIME from when to delete calls, optional" ) do|s| options[:start] = s end options[:start] = nil opts.on( '-E', '--end DATETIME', "DATETIME until when to delete calls" ) do|e| options[:end] = e end options[:limit] = nil opts.on( '-l', '--limit LIMIT', "LIMIT how much calls to delete in one go, if not specified calls in specified data range will be deleted in one go" ) do|l| options[:limit] = l end options[:transaction] = nil opts.on( '-t', '--transaction', "Set wheather to delete everything in transaction, by default OFF. should speed up things." ) do|t| options[:transaction] = t end options[:experimental] = nil opts.on( '-e', '--experimental', "Set if you want to try to delete old calls withoud actualy sending DELETE, by default OFF. should speed up things. in that case only end and transaction and drop_old prameters counts" ) do|e| options[:experimental] = e end options[:preserve] = nil opts.on( '-P', '--preserve', "Do not drop table with old calls. could be user if one if afraid to loose data or wants to make a backup. makes sence only if experimental 'deletion' was used." ) do|p| options[:preserve] = p end opts.on( '-h', '--help', 'Display this screen' ) do puts opts puts exit end end optparse.parse! #---------- SET CORECT PARAMS TO SCRIPT ! --------------- Debug_file = '/tmp/delete_old_calls.log' Database_name = options[:name].to_s.empty? ? 'mor' : options[:name] Database_username = options[:user].to_s.empty? ? 'mor' : options[:user] Database_password = options[:pasw].to_s.empty? ? 'mor' : options[:pasw] Database_host = options[:host].to_s.empty? ? 'localhost' : options[:host] Count_all = options[:all].to_s.empty? ? 0 : options[:all] #begin #---------- connect to DB ---------------------- ActiveRecord::Base.establish_connection(:adapter => "mysql", :database => Database_name, :username => Database_username, :password => Database_password, :host => Database_host) ActiveRecord::Base.connection #------------- Debug model ---------------- class Debug def Debug.debug(msg) File.open(Debug_file, "a") { |f| f << msg.to_s f << "\n" } #puts msg.to_s end end #------------------ Main ------------------- Debug.debug("\n*******************************************************************************************************") Debug.debug("#{Time.now().to_s(:db)} --- STARTING TO DELETE OLD CALLS ") if options[:start] and options[:end] condition = "calldate BETWEEN '#{options[:start]}' AND '#{options[:end]}'" elsif options[:end] condition = "calldate < '#{options[:end]}'" else raise 'ValueError. Must specify end of period' end if options[:experimental] Debug.debug("#{Time.now().to_s(:db)} --- using experimental call deletion method ") #it would be cool to drop indexes and then to receate them cause innodb can disable only unique key checks ActiveRecord::Base.connection.execute("CREATE TABLE tmp_calls LIKE calls"); ActiveRecord::Base.connection.execute("START TRANSACTION") if options[:transaction] ActiveRecord::Base.connection.execute("INSERT INTO tmp_calls SELECT * FROM calls WHERE calldate > '#{options[:end]}'") ActiveRecord::Base.connection.execute("COMMIT") if options[:transaction] ActiveRecord::Base.connection.execute("RENAME TABLE calls TO old_calls, tmp_calls TO calls") if !options[:preserve] Debug.debug("#{Time.now().to_s(:db)} --- droping table with old calls ") ActiveRecord::Base.connection.execute("DROP TABLE old_calls") else Debug.debug("#{Time.now().to_s(:db)} --- preserving table with old calls. you can can backup those calls any time.") end elsif options[:limit].to_i > 0 begin ActiveRecord::Base.connection.execute("START TRANSACTION") if options[:transaction] rows_affected = ActiveRecord::Base.connection.delete("DELETE FROM calls WHERE #{condition} LIMIT #{options[:limit].to_i}") ActiveRecord::Base.connection.execute("COMMIT") if options[:transaction] end while rows_affected > 0 else ActiveRecord::Base.connection.execute("START TRANSACTION") if options[:transaction] ActiveRecord::Base.connection.execute("DELETE FROM calls WHERE #{condition}") ActiveRecord::Base.connection.execute("COMMIT") if options[:transaction] end Debug.debug("#{Time.now().to_s(:db)} --- updateing call count information in card.call_count") ActiveRecord::Base.connection.execute("UPDATE cards JOIN (SELECT COUNT(*) call_count, card_id FROM calls WHERE card_id > 0 GROUP BY card_id) calls ON(calls.card_id = cards.id) SET cards.call_count = calls.call_count;") ActiveRecord::Base.remove_connection Debug.debug("#{Time.now().to_s(:db)} --- FINISED DELETING OLD CALLS ")