PostgreSQLの最近のブログ記事

Homebrew をインストールしたので、早速 PostgreSQL のインストールをしてみる。

まずは、brew でインストール可能な PostgreSQL を探す

% brew search postgresql
==> Formulae
postgresql@11    postgresql@12    postgresql@13    postgresql@14    postgresql@15    postgresql@16    postgresql@17    qt-postgresql    postgrest

==> Casks
navicat-for-postgresql                                                        posture-pal

If you meant "postgresql" specifically:
postgresql breaks existing databases on upgrade without human intervention.

See a more specific version to install with:
  brew formulae | grep postgresql@

postgres だけ指定したら最新バージョンで現行システム上書くでってことかな?
それで構わないので、今回は postgres だけ指定。

% brew install postgresql
Warning: Formula postgresql was renamed to postgresql@14.
==> Downloading https://ghcr.io/v2/homebrew/core/postgresql/14/manifests/14.13_3
<略>
This formula has created a default database cluster with:
  initdb --locale=C -E UTF-8 /opt/homebrew/var/postgresql@14

To start postgresql@14 now and restart at login:
  brew services start postgresql@14
Or, if you don't want/need a background service you can just run:
  /opt/homebrew/opt/postgresql@14/bin/postgres -D /opt/homebrew/var/postgresql@14
shinoda@shinodamasanorinoMacBook-Air smart_lap % brew services list     
Name          Status User File
postgresql@14 none  

これでインストール終了。

メッセージに起動方法が書かれているので、起動してみる。

% /opt/homebrew/opt/postgresql@14/bin/postgres -D /opt/homebrew/var/postgresql@14 &
[1] 34533
shinoda@shinodamasanorinoMacBook-Air smart_lap % 2024-11-13 20:40:08.668 JST [34533] LOG:  starting PostgreSQL 14.13 (Homebrew) on aarch64-apple-darwin24.1.0, compiled by Apple clang version 16.0.0 (clang-1600.0.26.4), 64-bit
<略>

クライアントソフトの psql も実行してみる。

% psql --version
psql (PostgreSQL) 14.13 (Homebrew)

うむ。ちゃんとインストールされているな。

ちなみに、Homebrew でインストールした場合は、brew services コマンドでの起動もできるようだ。

起動して、すぐに停止してみる。

% brew services start postgresql
Warning: Formula postgresql was renamed to postgresql@14.
==> Successfully started `postgresql@14` (label: homebrew.mxcl.postgresql@14)
% brew services stop postgresql
Warning: Formula postgresql was renamed to postgresql@14.
Stopping `postgresql@14`... (might take a while)
==> Successfully stopped `postgresql@14` (label: homebrew.mxcl.postgresql@14)

問題なし。
さて、続いて PostgreSQL の設定をするか。
俺も「軽い」macOS ユーザなので、アプリのインストールは DMG ファイルから行ったり、ZIP ファイルを解凍してアプリケーションフォルダにコピーしたり、そういうやり方しか知らなかった。パッケージマネージャなど使ったことがなかった。

しかし、DBMS(今回入れるのは PostgreSQL)のインストールにはパッケージマネージャから入れておいたほうが後々バージョンアップとか楽だということなので、今回 Homebrew を入れてみた。

とりあえずターミナル上で、brew を実行してみると、

% brew --version
zsh: command not found: brew

とエラーが。うむ。新規インストールせねば。

Homebrew の公式サイトに載っている手順通りに実施。
サイトから curl で最新のインストーラを取ってきて実行。

% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
==> Checking for `sudo` access (which may request your password)...
Password:<macOS ユーザのパスワード>
==> This script will install:
/opt/homebrew/bin/brew
/opt/homebrew/share/doc/homebrew
/opt/homebrew/share/man/man1/brew.1
<以下略>

これだけでインストールは終了。

ただ、これだけだと brew のパスが通ってないので、ターミナルに出力されているインストールメッセージの Next Step に書かれているコマンドを実行しろと言われる。

Warning: /opt/homebrew/bin is not in your PATH.
  Instructions on how to configure your shell for Homebrew
  can be found in the 'Next steps' section below.

言われたとおりに実行してみる。

% echo >> /Users/hogehoge/.zprofile
% echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/hogehoge/.zprofile
% eval "$(/opt/homebrew/bin/brew shellenv)"

その後、brew を実行してみる。

% brew --version
Homebrew 4.4.4

バッチリ(笑)
20241107_sql_error.jpg

PostgreSQL でカラム(列)追加するときって、

ALTER TABLE table1 ADD col1 CHARACTER VARYING(10)

で OK なんだが、ADD の後ろに COLUMN って付けたらダメじゃったんかいねえ?

AS:SQL Mk-2 の SQL 窓で

ALTER TABLE table1 ADD COLUMN col1 CHARACTER VARYING(10)

ってすると、「キーワード 'COLUMN' 付近に不適切な構文があります」ってエラーになっちゃう。

久しぶりなんで記憶が今一つ曖昧だけど・・・

仕事で SQLServer、MySQL、PostgreSQL を使っているんだが、最近は MySQL が多かったんで記憶がごっちゃになってたけど、PostgreSQL では ADD COLUMN はエラーだけど、MySQL は ADD だけでも ADD COLUMN でもどっちでもいいんやな。

もう、すっかり ADD COLUMN って打つのが癖になってたわ。
つーか、PostgreSQL も ADD COLUMN くらい許せよ(^^;;;
うーん・・・

LibreOffice の Python マクロで FeliCa カードの連続読み込みができない。

こういうソース(無限ループしてるけど、テストで break 処理書くのが面倒くさかっただけなんで(^^;;)をマクロ登録して、CardRead 関数を実行する。

# -*- coding: utf-8 -*-
# LibreOffice 用マクロ

import uno

def CardRead(*args):

    import nfc
    from nfc.clf import RemoteTarget

    def on_connect(tag):
        doc = XSCRIPTCONTEXT.getDocument()
        sheet = doc.getSheets().getByName('CardMst')
        cell = sheet.getCellByPosition(1,1)
        cell.String = str(tag)

    def main():
        while True:
            with nfc.ContactlessFrontend('usb') as clf:
                clf.connect(rdwr={'on-connect': on_connect})

    main()

そうすると、一枚目はちゃんと読み込んでシートの左上に ID が表示されるんだけど、二枚目のカードを読むと

com.sun.star.uno.RuntimeException: Error during invoking function CardRead in module file:///C:/Program%20Files/LibreOffice/share/Scripts/python/nfc_get_card_info.py (<class 'usb1.USBErrorAccess'>: LIBUSB_ERROR_ACCESS [-3]
  File "C:\Program Files\LibreOffice\program\pythonscript.py", line 907, in invoke
    ret = self.func( *args )
<略>
  File "C:\Users\hoge\AppData\Roaming\Python\Python35\site-packages\usb1\__init__.py", line 125, in raiseUSBError
    raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
)

こんなエラーが出ちゃう。これ以降、一切カードは読めない。

どうも、権限の無いアクセスを USB デバイスにしたってことらしい(ちょっとググったが英語のページしかヒットしなかったので意訳(^^; 違ってたら正解を教えてくれナンス>識者の皆様)

ちなみに、このスクリプトをマクロではなく普通の Python スクリプトとして実行すると、そういうエラーは出ない。マクロ独自の症状のようだ。

結局、どうしてもこのエラーを解決できなかったので、外部の Python スクリプトとして実行しておいて、カード情報を読み込んだら内容を CSV ファイルに吐いて、LibreOffice Calc からその CSV ファイルを一定時間毎に読み込む形にしようと思ってるところだけど、「お前、馬鹿だなあ。こう直したら一発で解決だべ」って情報をお持ちの識者の方がいらっしゃったら、ぜひご教示くださいませ。
昨夜、お客さんの DB データのメンテナンスをした。最新情報を CSV ファイルで欲しいということだったので、COPY コマンドでエクスポートしようとしたんだけど、

hogedb=# COPY m_hoge TO '/tmp/m_hoge_20180511.csv' WITH CSV DELIMITER ',' NULL AS '' HEADER FORCE QUOTE *;
ERROR:  syntax error at or near "*"
LINE 1: ...csv' WITH CSV DELIMITER ',' NULL AS '' HEADER FORCE QUOTE *;

て具合にエラーになる。FORCE QUOTE のワイルドカード文字 '*' が引っかかっているようだ。

うーん、なんで?
全カラムをダブルクォーテーションで囲むのであれば、FORCE QUOTE * じゃなかったっけ?

取り敢えず、

hogedb=# COPY m_hoge TO '/tmp/m_hoge_20180511.csv' WITH CSV DELIMITER ',' NULL AS '' HEADER FORCE QUOTE id,name,kubun,hoge1,hoge2,note,cdate,udate;
COPY 84

みたいに全項目名を書けば上手くいったけど、項目数が何十ってあるテーブルだってあるわけで、いちいちそれを羅列するの?・・・って話だなあ。

なんでワイルドカード使えんのやろ?

バージョンは PostgreSQL 8.4.20 でちょっと古いんだけど、8 の時ってワイルドカード、使えんかったっけ?

確かに、PostgreSQL 9.0.4 だったらエラーにならないなあ。
CentOS 上の PostgreSQL を Windows 8 Pro 上の A5:SQL Mk-2 64bit Edition Version 2.10.1(汎用SQL開発ツール/ER図ツール)を使って操作しているのだが、

character 0xfac9 of encoding "EUC_JP" has no equivalent in "UTF8"

のようなエラーが出て見れないテーブルがある。
元の DB が EUC-JP で作られており、それを UTF-8 に変換して結果を返そうとして PostgreSQL が出しているエラーのようである。
つまり、EUC-JP で 0xFAC9 である文字コードを、UTF-8 の 0xE6A192 に変換できないってことだな。

ちなみに問題の漢字は「桒」。「桑」の俗字なんだけど、この字を使った苗字とか存在してて(俺も一人知ってる)、「桒原」と書けば「くわばら」と読む。
一応、Shift_JIS や JIS、UTF-8、UTF-16 にも存在している文字である・・・が、「俗字」ということで、ハシラダカ「髙」なんかと同じように、OS や DBMS によって実装で色々もめている文字ではある(^^;

PostgreSQL のソースに含まれる EUC-JP→UTF-8 変換用のマッピングファイル(src/backend/utils/mb/Unicode/euc_jp_to_utf8.map)を確認すると、確かに 0xFAC9 から 0xE6A192 への変換情報は存在していないようだ。

 ~
  {0xf4a5, 0xe5879c},
  {0xf4a6, 0xe78699},
  {0x8fa2af, 0xcb98},
  {0x8fa2b0, 0xcb87},
 ~

0xF4A6 の次は、もういきなり 3バイト EUC コードの 0x8FA2AF になってる。
(0xF9A1~0xFCFE 間の 374文字は変換テーブルに載せてもらえてないようだ(^^;)

対応方法として、この間に、{0xfac9, 0xe6a192} という情報を追加してやって、もう一度 PostgreSQL をコンパイルしてやればいい。
(UTF-8→EUC-JP 変換用の utf8_to_euc_jp.map にも逆向きの情報を登録してやる必要あり)

が、これ、お客さんところの環境なので勝手にコンパイルするわけにもいかず(^^;

まあ、A5:SQL が UTF-8 への変換を要求しているのが問題なわけで、EUC-JP のまま使うのであれば問題ない。文字コード EUC-JP で SSH 接続して、ターミナル上で psql 使うしかないか(^^;

<参考>
PostgreSQL の話。

テスト用に DB のコピーを作る時、今までは「新しい DB を createdb で作成」「元の DB を pg_dump で丸々ダンプ(pg_dumpall に非ず)」「psql でダンプファイルから新しい DB にリストア」「ユーザ権限関係とか調整」とか色々作業してたんだけど、一発で DB のコピーできたんだね。

新しい DB を作る時に、

$ createdb -T old_db new_db

って感じでテンプレートデータベースとして元の DB を指定すれば、この DB の内容丸コピー(データも含めて)で新しい DB が作成されるんやね~
知らんかった。
まあ、そんなに何度もやることじゃないので、pg_dump 実行してほげほげで困らなかった(もう、この方法を知ってしまったので今後は pg_dump ほげほげ面倒くさいけれど(^^;)んだけど、今後はこの方法で一発やね。

ただ、この時、old_db がその瞬間使われていたら、

createdb: database creation failed: ERROR:  source database "old_db" is being accessed by other users

みたいなエラーが出ちゃう。
この時は、old_db へのセッションプロセスを全部 kill しちゃおう。

$ ps -auxww|grep post

とかすれば、

postgres  7186  0.0  0.0  6468 1600 pts/2    S+   14:20   0:00 psql old_db

こんなプロセスが引っかかるので、

$ kill -9 7186

とかして殺していく。
これで、createdb が問題なく出来るぞ。むふん。
仕様変更があって、既に本番稼働しているシステムに手を加えないといけなくなった。
具体的には、データベースのあるテーブルのあるカラムを VARCHAR(24) から VARCHAR(48) に変更する。

ま、使ってる DBMS が PostgreSQL なんで、psql で DB にログインして

ALTER TABLE table_hogehoge ALTER COLUMN column1 TYPE varchar(48);

実行するだけや・・・と、実際にうちのサーバにテスト環境作って確認。バッチリなので本番環境で実行してみると・・・

ERROR:  syntax error at or near "TYPE" at character 46

だって・・・(^^;

見てみたら、お客さんとこの PostgreSQL はバージョンが 7.4.19・・・
そりゃ駄目だ。上記のコマンドはメジャーバージョンが 8 からしか使えんし・・・
(ちなみにうちのテスト環境の PostgreSQL は 9.0.4)

仕方ないので、

BEGIN;
ALTER TABLE table_hogehoge ADD COLUMN new_column1 varchar(48);
UPDATE table_hogehoge SET new_column1 = CAST(column1 AS varchar(48));
ALTER TABLE table_hogehoge DROP COLUMN column1;
ALTER TABLE table_hogehoge RENAME COLUMN new_column1 TO column1;
COMMIT;

という、「新しい VARCHAR(48)なカラムを作って、元のカラムのデータを移し、元のカラムを削除した後で、新しいカラムの名前を元のカラムのものに変更」・・・という面倒臭い手順を経てサイズ変更には成功。

但し、この方法だとカラムの位置がずれるので(新しいカラムはテーブルの一番最後に追加される)、プログラムの中でテーブルの内容を二次元配列にセットしている箇所なんかは全部直さないといけなくなった。とほほ。

昔から俺は「変なサーバ」と呼んでる某地場企業のホスティングサーバで、海外のサーバ管理システムを使っているらしんだけど「セキュリティをガチガチにしたあげくに使い勝手が悪くなってる」典型みたいなサーバ(^^;
PostgreSQL も俺の方で勝手にバージョン上げたり出来ないのでどうしようもない。(何せ、本来有るはずの PostgreSQL のコマンドのいくつかも「セキュリティ上の理由」で削除されているような特殊な環境だ(^^;)

まあ、色々しがらみもあって「サーバ載せ替えて」というのも難しいので、しばらくこの「泥棒を入れないためにドアを溶接して住人も入れなくなった家」みたいなサーバとは付き合っていく必要があるのである(^^;
大した話ではないし、PostgreSQL のドキュメントにも記載があることなので、わざわざここでメモるほどのことではないのだが、うっかりエラーを出してドキっとしたので書いておく。

PostgreSQL で、既存テーブルに列を追加し、NOT NULL にする手順。

例えば、hoge テーブルに、chin と man という列を追加するのなら、以下の SQL を実行する。

ALTER TABLE hoge ADD COLUMN chin VARCHAR(1);
ALTER TABLE hoge ADD COLUMN man VARCHAR(1);

これでテーブルの末尾に上記2つの列が追加されるが、NULL も許可する形で作られている。

ADD COLUMN では、

ALTER TABLE hoge ADD COLUMN chin VARCHAR(1) NOT NULL;

というように、CREATE TABLE する時の書式(NOT NULL)が使えない。
後で、SET NOT NULL してやらないといけない。

・・・が、ADD COLUMN した後で、そのまますぐに SET NOT NULL するとエラーになる。

hoge=# ALTER TABLE hoge ALTER COLUMN chin SET NOT NULL;
ERROR:  column "chin" contains null values

「既に NULL 値がセットされちゃってるから、NOT NULL 出来ねえよ。こんにゃろ!」と PostgreSQL に怒られてるわけだ。まあ、そりゃそうだよな。設定とデータの中身がいきなり不整合ってことになっちゃうからな(^^;

そこで、一旦、

UPDATE hoge SET chin='0', man='0';

という SQL を実行して、追加した列に値(例 '0')をセットする。
これで、

ALTER TABLE hoge ALTER COLUMN chin SET NOT NULL;
ALTER TABLE hoge ALTER COLUMN man SET NOT NULL;

を実行しても、エラーは出ず、ちゃんとテーブルに NOT NULL 項目として追加される。

ああ、面倒くさい(^^;
またも、libpq.so.5 がらみのエラーで小一時間悩む・・・

実は、これで三回目である。
この問題で時間を無駄にしたのは・・・

シェル上での実行(ちなみに、root ユーザにて)ではまったく問題無いのに、CGI で実行すると、

install_driver(Pg) failed: Can't load '/usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/DBD/Pg/Pg.so' for module DBD::Pg: libpq.so.5: cannot open shared object file: No such file or directory at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/DynaLoader.pm line 230, <DATA> line 855.
 at (eval 9) line 3
Compilation failed in require at (eval 9) line 3, <DATA> line 855.
Perhaps a required shared library or dll isn't installed where expected
 at ../hogehoge.cgi line 99

というエラーが出る。

結論から言おう。
これは、「POSTGRES_HOME のパーミッション」の問題(^^;

/usr/local/pgsql ディレクトリが 0700(所有者以外、参照すら不可)で作られているので、Apache の実行ユーザである daemon から libpq.so.5(/usr/local/pgsql/lib)の参照が出来ないために No such file or directory となっている。

つーことで、/usr/local/pgsql ディレクトリのパーミッションを 0755 に変更すれば解決。

以前(特に FreeBSD サーバメインだった頃)は、mkdir /usr/local/pgsql してから、vipw や vi /etc/group で直接ユーザー&グループの作成を行っていたので、POSTGRES_HOME(/usr/local/pgsql)が 0700 で作られることはなかったんだが、最近は手っ取り早く、

# groupadd -g 128 postgres
# useradd -g postgres -u 128 -c 'POSTGRES Admin' -d /usr/local/pgsql -m -s /bin/bash postgres

ってやっちゃうからな。これだと、/usr/local/pgsql が 0700 で作られちゃう。

ググっても、「httpd.conf で mod_env が有効になっているのを確認して SetEnv LD_LIBRARY_PATH /usr/local/pgsql/lib という記述を追加しよう」とか、「ldconfig してないんじゃないか?」的な情報が多いんだけど、俺がそんなミスするかよ!!

・・・って、俺のミスの方がよっぽど格好悪いけどな(^^; とほほほ・・・

このアーカイブについて

このページには、過去に書かれたブログ記事のうちPostgreSQLカテゴリに属しているものが含まれています。

前のカテゴリはMySQLです。

次のカテゴリはSQLです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら