sql_cmd 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 266298d96407b2fb372453d3989ef5fb21047f1a364c857c3c559e1826257d5a
4
- data.tar.gz: b3053a685e3e0202e1b68bddb20cec62bce549f6d7a8f7164ead4709f355dd9a
3
+ metadata.gz: 4df6d540e8235db2ebe06497947f8be105e7232f040d988378f75996be6624c2
4
+ data.tar.gz: c2b4f51d378cd9b7372aca4b364270756d3a55640d85110e9999c5f79c52e243
5
5
  SHA512:
6
- metadata.gz: 99aab9a7af85a77a7da945aaff55823364b497ef4d91d2551994362d87120c379784b8ff753d4339ac44ca91d14ba1c02f17f07942c03646f956c5c9da609190
7
- data.tar.gz: 5c6b0287eb928e2356e99b329eee771f5add55af0b13d0ec29e131fee1ab1590c7c726dcfd280d25b96e753b5febc8626841c844e4ae1f122468b8270d19e923
6
+ metadata.gz: fa6c6886afc7595a4cdacd0fceeb1dc10aa5ad2edc0f440bcabe634ec1d35978acaee61eae509db8bfe56418d867bfed95a32a1f318362dd3377d6d3b9a5edba
7
+ data.tar.gz: b233b667fe7e1942efb56bd8a0cf20162f46405f1ff5ab3bd41ddcf768e67064aa57b3934d8aa0fcc197188bc886ab6b596adb61498637da6c9cf4ad10fa2bb5
@@ -263,5 +263,10 @@ module SqlCmd
263
263
  raise 'Failed to remove database from AlwaysOn Availability Group' unless database_info['AvailabilityGroup'].nil? && replica_database_info['AvailabilityGroup'].nil?
264
264
  EasyIO.logger.info "[#{database_name}] removed from AlwaysOn availability group successfully..."
265
265
  end
266
+
267
+ def enabled?(connection_string)
268
+ server_info = SqlCmd.get_sql_server_settings(connection_string)
269
+ server_info['AvailabilityGroup'].nil? || server_info['SecondaryReplica'].nil?
270
+ end
266
271
  end
267
272
  end
@@ -54,22 +54,27 @@ module SqlCmd
54
54
  files.map { |f, properties| ["#{base_url}/#{f}", properties[:last_modified]] }.to_h
55
55
  end
56
56
 
57
- def backup_location_and_basename(start_time, connection_string, database_name, options = {}, backup_url: nil)
57
+ def backup_location_and_basename(start_time, connection_string, database_name, options = {}, backup_folder: nil, backup_url: nil, backup_basename: nil)
58
58
  start_time = SqlCmd.unify_start_time(start_time)
59
59
  database_info = SqlCmd::Database.info(connection_string, database_name)
60
60
  server_settings = get_sql_server_settings(connection_string)
61
61
  backup_type = backup_url.nil? || backup_url.empty? ? 'DISK' : 'URL'
62
62
  if database_info['DatabaseNotFound']
63
- backup_name = "#{database_name}_#{EasyTime.yyyymmdd(start_time)}"
64
- return [backup_url, backup_name] if backup_type == 'URL'
63
+ backup_basename = "#{database_name}_#{EasyTime.yyyymmdd(start_time)}"
64
+ return [backup_url, backup_basename] if backup_type == 'URL'
65
65
  backup_unc_location = SqlCmd.config['sql_cmd']['backups']['backup_to_host_sql_server'] ? "\\\\#{server_settings['ServerName']}\\#{SqlCmd.config['sql_cmd']['backups']['default_backup_share']}" : SqlCmd.config['sql_cmd']['backups']['default_destination']
66
- return Dir.glob("#{backup_unc_location}/#{backup_name}*".tr('\\', '/')).empty? ? [nil, nil] : [backup_unc_location, backup_name]
66
+ return Dir.glob("#{backup_unc_location}/#{backup_basename}*".tr('\\', '/')).empty? ? [nil, nil] : [backup_unc_location, backup_basename]
67
67
  end
68
68
 
69
69
  backup_file_path = database_info['BackupFileLocation']
70
+ if backup_file_path =~ /^\{.*\}$/
71
+ backup_basename ||= "#{database_name}_#{EasyTime.yyyymmdd(start_time)}"
72
+ backup_files, backup_basename = SqlCmd::Database.existing_backup_files(server_settings, options, backup_folder: backup_folder, backup_url: backup_url, backup_basename: backup_basename, log_only: options['logonly'])
73
+ backup_file_path = backup_files.first
74
+ end
70
75
  backup_file = ::File.basename(backup_file_path)
71
- backup_name = backup_basename(backup_file)
72
- return [nil, backup_name] if backup_type == 'URL'
76
+ backup_basename = backup_basename_from_path(backup_file)
77
+ return [nil, backup_basename] if backup_type == 'URL'
73
78
  backup_unc_location = to_unc_path(::File.dirname(backup_file_path), server_settings['ServerName'])
74
79
  backup_folder = if ::File.exist?("#{backup_unc_location}/#{backup_file}")
75
80
  backup_unc_location
@@ -77,7 +82,7 @@ module SqlCmd
77
82
  "\\\\#{server_settings['ServerName']}\\#{SqlCmd.config['sql_cmd']['backups']['default_backup_share']}"
78
83
  end
79
84
  return [nil, nil] unless defined?(backup_folder)
80
- [backup_folder, backup_name]
85
+ [backup_folder, backup_basename]
81
86
  end
82
87
 
83
88
  # sql_server_settings can be for any server that has network access to these files
@@ -313,10 +313,10 @@ module SqlCmd
313
313
  SqlCmd.run_sql_as_job(connection_string, sql_backup_script, "Backup: #{backup_basename}", values: values, retries: 1, retry_delay: 30)
314
314
  end
315
315
 
316
- def monitor_backup(backup_start_time, connection_string, database_name, options = {}, backup_folder: nil, backup_url: nil, backup_basename: nil, log_only: false, retries: 3, retry_delay: 10)
316
+ def monitor_backup(backup_start_time, connection_string, database_name, options = {}, job_name: nil, backup_folder: nil, backup_url: nil, backup_basename: nil, log_only: false, retries: 3, retry_delay: 10)
317
317
  backup_start_time = SqlCmd.unify_start_time(backup_start_time)
318
318
  backup_status_script = ::File.read("#{SqlCmd.sql_script_dir}/Status/BackupProgress.sql")
319
- job_name = "Backup: #{database_name}"
319
+ job_name ||= "Backup: #{database_name}"
320
320
  EasyIO.logger.info 'Checking backup status...'
321
321
  EasyIO.logger.debug "Backup start time: #{backup_start_time}"
322
322
  sleep(3) # Give the job time to start
@@ -340,9 +340,9 @@ module SqlCmd
340
340
  # job_message = job_history_message(connection_string, job_name) unless result == :current
341
341
  if job_started # Check if job has timed out after stopping without completing
342
342
  job_completion_time ||= Time.now
343
- _raise_backup_failure(connection_string, database_name, last_backup_date_key, backup_start_time, backup_basename, job_status: job_status, job_started: job_started) if Time.now > job_completion_time + timeout
343
+ _raise_backup_failure(connection_string, database_name, last_backup_date_key, backup_start_time, job_name, job_status: job_status, job_started: job_started) if Time.now > job_completion_time + timeout
344
344
  elsif Time.now > monitoring_start_time + timeout # Job never started and timed out
345
- _raise_backup_failure(connection_string, database_name, last_backup_date_key, backup_start_time, backup_basename, job_status: job_status, job_started: job_started)
345
+ _raise_backup_failure(connection_string, database_name, last_backup_date_key, backup_start_time, job_name, job_status: job_status, job_started: job_started)
346
346
  end
347
347
  sleep(timer_interval)
348
348
  next
@@ -380,18 +380,18 @@ module SqlCmd
380
380
  result
381
381
  end
382
382
 
383
- def _raise_backup_failure(connection_string, database_name, last_backup_date_key, backup_start_time, backup_basename, job_status: nil, job_started: false)
383
+ def _raise_backup_failure(connection_string, database_name, last_backup_date_key, backup_start_time, job_name, job_status: nil, job_started: false)
384
384
  server_name = SqlCmd.connection_string_part(connection_string, :server)
385
- if job_started
386
- failure_message = "Backup may have failed as the backup has stopped and the last backup time shows #{SqlCmd::Database.info(connection_string, database_name)[last_backup_date_key]} " \
387
- "but the backup should be newer than #{backup_start_time}! "
388
- failure_message += job_status == 'NoJob' ? 'The job exited with success and so does not exist!' : "Check sql job 'Backup: #{backup_basename}' history on [#{server_name}] for details. \n"
389
- raise failure_message + "Last backup time retrieved from: #{server_name}\\#{database_name}"
390
- end
391
- failure_message = "Backup appears to have failed! The last backup time shows #{SqlCmd::Database.info(connection_string, database_name)[last_backup_date_key]} " \
392
- "but the backup should be newer than #{backup_start_time}! "
393
- failure_message += job_status == 'NoJob' ? 'The backup job could not be found!' : "The job did not start in time. Check sql job 'Backup: #{backup_basename}' history on [#{server_name}] for details."
394
- raise failure_message + "Last backup time retrieved from: #{server_name}\\#{database_name}"
385
+ failure_message = if job_started
386
+ "Backup may have failed as the backup has stopped and the last backup time shows #{SqlCmd::Database.info(connection_string, database_name)[last_backup_date_key]} " \
387
+ "but the backup should be newer than #{backup_start_time}! " +
388
+ (job_status == 'NoJob' ? 'The job exited with success and so does not exist!' : "Check sql job '#{job_name}' history on [#{server_name}] for details. \n")
389
+ else
390
+ "Backup appears to have failed! The last backup time shows #{SqlCmd::Database.info(connection_string, database_name)[last_backup_date_key]} " \
391
+ "but the backup should be newer than #{backup_start_time}! " +
392
+ (job_status == 'NoJob' ? 'The backup job could not be found!' : "The job did not start in time. Check sql job '#{job_name}' history on [#{server_name}] for details.")
393
+ end
394
+ raise failure_message + " Last backup time retrieved from: #{server_name}\\#{database_name}"
395
395
  end
396
396
 
397
397
  # Creates and starts a SQL job to restore a database.
@@ -500,8 +500,8 @@ module SqlCmd
500
500
  database_info = info(connection_string, database_name) if database_info.nil?
501
501
  server_name = SqlCmd.connection_string_part(connection_string, :server)
502
502
  EasyIO.logger.info "Ensuring full backup has taken place for [#{server_name}].[#{database_name}]..."
503
- if force_backup || database_info['LastNonCopyOnlyFullBackupDate'].nil? || # Ensure last full backup occurred AFTER the DB was last restored
504
- (!database_info['LastRestoreDate'].nil? && database_info['LastNonCopyOnlyFullBackupDate'] < database_info['LastRestoreDate'])
503
+ start_time = database_info['LastRestoreDate'] || database_info['create_date']
504
+ if force_backup || database_info['LastNonCopyOnlyFullBackupDate'].nil? || (database_info['LastNonCopyOnlyFullBackupDate'] < start_time) # Ensure last full backup occurred AFTER the DB was last restored/created
505
505
  EasyIO.logger.info 'Running full backup...'
506
506
  backup_basename = "full_backup-#{database_name}_#{EasyTime.yyyymmdd}" # If a full_backup_method was not provided, use this name for the database backup for clarity
507
507
  full_backup_method.nil? ? SqlCmd::Database.backup(Time.now, connection_string, database_name, backup_basename: backup_basename, options: { 'copyonly' => false }) : full_backup_method.call
@@ -511,7 +511,7 @@ module SqlCmd
511
511
  def duplicate(start_time, source_connection_string, source_database_name, destination_connection_string, destination_database_name, backup_folder: nil, backup_url: nil, backup_basename: nil, force_restore: false, full_backup_method: nil, options: {})
512
512
  start_time = SqlCmd.unify_start_time(start_time)
513
513
  backup(start_time, source_connection_string, source_database_name, backup_folder: backup_folder, backup_url: backup_url, backup_basename: backup_basename, options: options) unless info(source_connection_string, source_database_name)['DatabaseNotFound']
514
- backup_folder, backup_basename = SqlCmd.backup_location_and_basename(start_time, source_connection_string, source_database_name, options, backup_url: backup_url) # TODO: rework for URL
514
+ backup_folder, backup_basename = SqlCmd.backup_location_and_basename(start_time, source_connection_string, source_database_name, options, backup_folder: backup_folder, backup_url: backup_url, backup_basename: backup_basename) # TODO: rework for URL
515
515
  if (backup_folder.nil? && backup_url.nil?) || backup_basename.nil?
516
516
  source_server = SqlCmd.connection_string_part(source_connection_string, :server)
517
517
  destination_server = SqlCmd.connection_string_part(destination_connection_string, :server)
@@ -85,7 +85,7 @@ module SqlCmd
85
85
  end
86
86
 
87
87
  # get the basename of the backup based on a full file_path such as the SQL value from [backupmediafamily].[physical_device_name]
88
- def backup_basename(backup_path)
88
+ def backup_basename_from_path(backup_path)
89
89
  return nil if backup_path.nil? || backup_path.empty?
90
90
  ::File.basename(backup_path).gsub(/(\.part\d+)?\.(bak|trn)/i, '')
91
91
  end
data/lib/sql_cmd/query.rb CHANGED
@@ -83,7 +83,18 @@ module SqlCmd
83
83
  raise
84
84
  end
85
85
  ensure
86
- ::File.delete "#{@scripts_cache_windows}\\sql_helper_#{start_time}.ps1" if defined?(start_time) && ::File.exist?("#{@scripts_cache_windows}\\sql_helper_#{start_time}.ps1")
86
+ retry_count = 0
87
+ retries = 3
88
+ retry_delay = 3
89
+ begin
90
+ ::File.delete "#{@scripts_cache_windows}\\sql_helper_#{start_time}.ps1" if defined?(start_time) && ::File.exist?("#{@scripts_cache_windows}\\sql_helper_#{start_time}.ps1")
91
+ rescue # Try to delete the file 3 times
92
+ if (retry_count += 1) <= retries
93
+ sleep(retry_delay)
94
+ retry
95
+ end
96
+ raise
97
+ end
87
98
  end
88
99
 
89
100
  def convert_powershell_tables_to_hash(json_string, return_type = :all_tables, at_timezone: 'UTC', string_to_time_by: '%Y-%m-%d %H:%M:%S %z') # options: :all_tables, :first_table, :first_row
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sql_cmd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Munoz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-15 00:00:00.000000000 Z
11
+ date: 2022-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: easy_json_config