В общем то ничего принципиально нового для моих разработок новые версии PostgreSQL не несут и можно вполне пользоваться старыми, но я люблю когда софтина последней версии, кроме того, рано или позно мигрировать все равно надо будет, поскольку старую версию когда-нибудь да выпилят.
Собственно в чем проблема? Проблема в том, что разные версии PostgreSQL хранят данные в разных папках и тупо скопировать/переименовать старую папку в новую не получится - после такого новая версия просто не запускается.
Ок. Для этого есть стандартный приём - сделать дамп базы в старой версии и восстановить ее в новой.
По началу, чтобы не заморачиваться с консолькой и pg_dump, я решил заюзать что-то более дружелюбное.
Идущий в составе OpenServer последний официальный PhpPgAdmin не обновлялся много лет и с PHP7 не работает вообще. Есть работающий форк , но с экспортом через него тоже не вышло - данные-то он вроде выгружает, а вот структуру БД нет. Возможно в каком-то из 218 форков и это решено, но перебирать их все я не стал.
Далее я попробовал экспортировать БД с помощью HeidiSQL, но эта софтина мне вообще нифига не экспортировала, а только сыпала ошибками типа
/* ERROR: syntax error at or near "CREATE" LINE 1: SHOW CREATE DATABASE "public"
Все таки поддержка PostgreSQL в ней заявлена как экспериментальная. Хотя сообщения о такой проблеме были много билдов назад, могли бы и пофиксить уже.
В итоге дамп я выгрузил с помощью pg_dump.exe, но пока я гуглил как же это все таки сделать правильно, я наткнулся на упоминание pg_upgrade и решил попробовать ее.
Естественно с первого десятка раз нифига не получилось. Софтина неизменно писала в лог ошибку:
pg_ctl: unrecognized operation mode "50432"
В русской версии это звучит как "pg_ctl нераспознанный режим работы "50432"".
Собственно, софтина пытается запустить сервер PostgreSQL через pg_ctl на порту 50432 и у нее нифига не выходит. В логе pg_upgrade_server_start.log есть вся команда, которая пытается выполниться. Попытка выполнить запуск сервера этой же командой из консоли самостоятельно приводила к такому же результату. В команде в частности в параметре -o передаются параметры, которые будут переданы непосредственно исполнимому файлу postgres. Выглядел он так -o "-p 50432 -b ". То есть, теоретически, в postgres должен передаваться порт 50432. Какой нафиг режим работы?!
Я пошел проанализировал исходники pg_ctl и у меня закралось подозрение, что pg_ctl как-то не так парсит переданные ей параметры. В итоге до меня дошло. Причина оказалась в следующем.
Вызов pg_upgrade производился такой командой:
pg_upgrade.exe -b e:\Soft\OpenServer\modules\database\PostgreSQL-9.6-x64\bin\ -B e:\Soft\OpenServer\modules\database\PostgreSQL-10.5-x64\bin\ -d e:\Soft\OpenServer\userdata\PostgreSQL-9.6-x64\ -D e:\Soft\OpenServer\userdata\PostgreSQL-10.5-x64\
Тут -d - это путь к базе старой версии. В pg_ctl это попадало так (лишнее опущено:)
pg_ctl -D "e:\Soft\OpenServer\userdata\PostgreSQL-9.6-x64\" -o "-p 50432 -b " start
Обратите внимание на последний слэш в пути, выделенный красным. Судя по всему, pg_ctl считает что \" это не окончание параметра пути, а экранированный символ кавычек, и строка пути продолжается дальше. В итоге она не находит знакомой команды (в данном случае start, так как start становится значением параметра -b) и возникает ошибка.
В итоге если убрать все оконечные слэши в путях все запускается и отрабатывает на ура. Единственное, еще нужно добавить параметр -U postgres для pg_upgrade (и возможно запускать от имени администратора). Таким образом, итоговая работающая команда выглядит так:
pg_upgrade.exe -b e:\Soft\OpenServer\modules\database\PostgreSQL-9.6-x64\bin -B e:\Soft\OpenServer\modules\database\PostgreSQL-10.5-x64\bin -d e:\Soft\OpenServer\userdata\PostgreSQL-9.6-x64 -D e:\Soft\OpenServer\userdata\PostgreSQL-10.5-x64 -U postgres