| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  | require "abstract_command" | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  | require "formula" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  |   module Cmd | 
					
						
							|  |  |  |     class PostgresqlUpgradeDatabase < AbstractCommand | 
					
						
							|  |  |  |       cmd_args do | 
					
						
							|  |  |  |         description <<~EOS | 
					
						
							|  |  |  |           Upgrades the database for the `postgresql` formula. | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  |         named_args :none | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  |         hide_from_man_page! | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  |       sig { override.void } | 
					
						
							|  |  |  |       def run | 
					
						
							|  |  |  |         odisabled "brew postgresql_upgrade_database", | 
					
						
							|  |  |  |                   "using new, versioned e.g. `var/postgres@14` datadir and `pg_upgrade`" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         name = "postgresql" | 
					
						
							|  |  |  |         pg = Formula[name] | 
					
						
							|  |  |  |         bin = pg.bin | 
					
						
							|  |  |  |         var = pg.var | 
					
						
							|  |  |  |         version = pg.version | 
					
						
							|  |  |  |         pg_version_file = var/"postgres/PG_VERSION" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pg_version_installed = version.to_s[/^\d+/] | 
					
						
							|  |  |  |         pg_version_data = pg_version_file.read.chomp | 
					
						
							|  |  |  |         if pg_version_installed == pg_version_data | 
					
						
							|  |  |  |           odie <<~EOS | 
					
						
							|  |  |  |             #{name} data already upgraded! | 
					
						
							|  |  |  |           EOS | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  |         datadir = var/"postgres" | 
					
						
							|  |  |  |         old_datadir = var/"postgres.old" | 
					
						
							|  |  |  |         if old_datadir.exist? | 
					
						
							|  |  |  |           odie <<~EOS | 
					
						
							|  |  |  |             #{old_datadir} already exists! | 
					
						
							|  |  |  |             Remove it if you want to upgrade data automatically. | 
					
						
							|  |  |  |           EOS | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         old_pg_name = "#{name}@#{pg_version_data}" | 
					
						
							|  |  |  |         old_pg_glob = "#{HOMEBREW_CELLAR}/#{old_pg_name}/#{pg_version_data}.*/bin" | 
					
						
							|  |  |  |         old_bin = Pathname.glob(old_pg_glob).first | 
					
						
							|  |  |  |         old_bin ||= begin | 
					
						
							|  |  |  |           Formula[old_pg_name] | 
					
						
							|  |  |  |           ohai "brew install #{old_pg_name}" | 
					
						
							|  |  |  |           system HOMEBREW_BREW_FILE, "install", old_pg_name | 
					
						
							|  |  |  |           Pathname.glob(old_pg_glob).first | 
					
						
							|  |  |  |         rescue FormulaUnavailableError | 
					
						
							|  |  |  |           nil | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2024-04-01 09:48:23 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         odie "No #{name} #{pg_version_data}.* version installed!" unless old_bin | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         server_stopped = T.let(false, T::Boolean) | 
					
						
							|  |  |  |         moved_data = T.let(false, T::Boolean) | 
					
						
							|  |  |  |         initdb_run = T.let(false, T::Boolean) | 
					
						
							|  |  |  |         upgraded = T.let(false, T::Boolean) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         begin | 
					
						
							|  |  |  |           # Following instructions from: | 
					
						
							|  |  |  |           # https://www.postgresql.org/docs/10/static/pgupgrade.html | 
					
						
							|  |  |  |           ohai "Upgrading #{name} data from #{pg_version_data} to #{pg_version_installed}..." | 
					
						
							|  |  |  |           services_json_output = Utils.popen_read(HOMEBREW_BREW_FILE, "services", "info", "--all", "--json") | 
					
						
							|  |  |  |           services_json = JSON.parse(services_json_output) | 
					
						
							|  |  |  |           loaded_service_names = services_json.select { |sj| sj[:loaded] }.map { |sj| sj[:name] } | 
					
						
							|  |  |  |           if loaded_service_names.include?(name) | 
					
						
							|  |  |  |             system HOMEBREW_BREW_FILE, "services", "stop", name | 
					
						
							|  |  |  |             service_stopped = true | 
					
						
							|  |  |  |           elsif quiet_system "#{bin}/pg_ctl", "-D", datadir, "status" | 
					
						
							|  |  |  |             system "#{bin}/pg_ctl", "-D", datadir, "stop" | 
					
						
							|  |  |  |             server_stopped = true | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           # Shut down old server if it is up via brew services | 
					
						
							|  |  |  |           system HOMEBREW_BREW_FILE, "services", "stop", old_pg_name if loaded_service_names.include?(old_pg_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           # get 'lc_collate' from old DB" | 
					
						
							|  |  |  |           unless quiet_system "#{old_bin}/pg_ctl", "-w", "-D", datadir, "status" | 
					
						
							|  |  |  |             system "#{old_bin}/pg_ctl", "-w", "-D", datadir, "start" | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           initdb_args = T.let([], T::Array[String]) | 
					
						
							|  |  |  |           locale_settings = %w[
 | 
					
						
							|  |  |  |             lc_collate | 
					
						
							|  |  |  |             lc_ctype | 
					
						
							|  |  |  |             lc_messages | 
					
						
							|  |  |  |             lc_monetary | 
					
						
							|  |  |  |             lc_numeric | 
					
						
							|  |  |  |             lc_time | 
					
						
							|  |  |  |             server_encoding | 
					
						
							|  |  |  |           ] | 
					
						
							|  |  |  |           locale_settings.each do |setting| | 
					
						
							|  |  |  |             sql = "SELECT setting FROM pg_settings WHERE name LIKE '#{setting}';" | 
					
						
							|  |  |  |             value = Utils.popen_read("#{old_bin}/psql", "postgres", "-qtAX", "-U", ENV.fetch("USER"), "-c", | 
					
						
							|  |  |  |                                      sql).strip | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             next if value.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             initdb_args += if setting == "server_encoding" | 
					
						
							|  |  |  |               ["-E #{value}"] | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |               ["--#{setting.tr("_", "-")}=#{value}"] | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if quiet_system "#{old_bin}/pg_ctl", "-w", "-D", datadir, "status" | 
					
						
							|  |  |  |             system "#{old_bin}/pg_ctl", "-w", "-D", datadir, "stop" | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           ohai "Moving #{name} data from #{datadir} to #{old_datadir}..." | 
					
						
							|  |  |  |           FileUtils.mv datadir, old_datadir | 
					
						
							|  |  |  |           moved_data = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           (var/"postgres").mkpath | 
					
						
							|  |  |  |           ohai "Creating database..." | 
					
						
							|  |  |  |           safe_system "#{bin}/initdb", *initdb_args, "#{var}/postgres" | 
					
						
							|  |  |  |           initdb_run = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           ohai "Migrating and upgrading data..." | 
					
						
							|  |  |  |           (var/"log").cd do | 
					
						
							|  |  |  |             safe_system "#{bin}/pg_upgrade", | 
					
						
							|  |  |  |                         "-r", | 
					
						
							|  |  |  |                         "-b", old_bin, | 
					
						
							|  |  |  |                         "-B", bin, | 
					
						
							|  |  |  |                         "-d", old_datadir, | 
					
						
							|  |  |  |                         "-D", datadir, | 
					
						
							|  |  |  |                         "-j", Hardware::CPU.cores.to_s | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |           upgraded = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           ohai "Upgraded #{name} data from #{pg_version_data} to #{pg_version_installed}!" | 
					
						
							|  |  |  |           ohai "Your #{name} #{pg_version_data} data remains at #{old_datadir}" | 
					
						
							|  |  |  |         ensure | 
					
						
							|  |  |  |           if upgraded | 
					
						
							|  |  |  |             if server_stopped | 
					
						
							|  |  |  |               safe_system "#{bin}/pg_ctl", "-D", datadir, "start" | 
					
						
							|  |  |  |             elsif service_stopped | 
					
						
							|  |  |  |               safe_system HOMEBREW_BREW_FILE, "services", "start", name | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             onoe "Upgrading #{name} data from #{pg_version_data} to #{pg_version_installed} failed!" | 
					
						
							|  |  |  |             if initdb_run | 
					
						
							|  |  |  |               ohai "Removing empty #{name} initdb database..." | 
					
						
							|  |  |  |               FileUtils.rm_r datadir | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |             if moved_data | 
					
						
							|  |  |  |               ohai "Moving #{name} data back from #{old_datadir} to #{datadir}..." | 
					
						
							|  |  |  |               FileUtils.mv old_datadir, datadir | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |             if server_stopped | 
					
						
							|  |  |  |               system "#{bin}/pg_ctl", "-D", datadir, "start" | 
					
						
							|  |  |  |             elsif service_stopped | 
					
						
							|  |  |  |               system HOMEBREW_BREW_FILE, "services", "start", name | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2023-03-14 12:32:11 -04:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |