Class: Homebrew::Cmd::PostgresqlUpgradeDatabase

Inherits:
AbstractCommand show all
Defined in:
cmd/postgresql-upgrade-database.rb

Instance Attribute Summary

Attributes inherited from AbstractCommand

#args

Instance Method Summary collapse

Methods inherited from AbstractCommand

command, command_name, #initialize, parser

Constructor Details

This class inherits a constructor from Homebrew::AbstractCommand

Instance Method Details

#runvoid

This method returns an undefined value.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'cmd/postgresql-upgrade-database.rb', line 21

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
  end

  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
  end

  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
  end

  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
  end
end