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 +4 -4
- data/lib/sql_cmd/always_on.rb +5 -0
- data/lib/sql_cmd/backups.rb +12 -7
- data/lib/sql_cmd/database.rb +18 -18
- data/lib/sql_cmd/format.rb +1 -1
- data/lib/sql_cmd/query.rb +12 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4df6d540e8235db2ebe06497947f8be105e7232f040d988378f75996be6624c2
|
4
|
+
data.tar.gz: c2b4f51d378cd9b7372aca4b364270756d3a55640d85110e9999c5f79c52e243
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa6c6886afc7595a4cdacd0fceeb1dc10aa5ad2edc0f440bcabe634ec1d35978acaee61eae509db8bfe56418d867bfed95a32a1f318362dd3377d6d3b9a5edba
|
7
|
+
data.tar.gz: b233b667fe7e1942efb56bd8a0cf20162f46405f1ff5ab3bd41ddcf768e67064aa57b3934d8aa0fcc197188bc886ab6b596adb61498637da6c9cf4ad10fa2bb5
|
data/lib/sql_cmd/always_on.rb
CHANGED
@@ -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
|
data/lib/sql_cmd/backups.rb
CHANGED
@@ -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
|
-
|
64
|
-
return [backup_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}/#{
|
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
|
-
|
72
|
-
return [nil,
|
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,
|
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
|
data/lib/sql_cmd/database.rb
CHANGED
@@ -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
|
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,
|
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,
|
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,
|
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
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
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
|
-
|
504
|
-
|
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)
|
data/lib/sql_cmd/format.rb
CHANGED
@@ -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
|
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
|
-
|
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.
|
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-
|
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
|