sql_cmd 0.3.0 → 0.3.1
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 +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
|