タイトルの通りですが、PostgreSQL では、TRUNCATE TABLE も トランザクション内なので、ロールバックすると データは元に戻ります。
次のようになります。
postgres=# select * from test1; f1 | f2 ----+---- 1 | 1 2 | 2 (2 rows) postgres=# begin; BEGIN postgres=# truncate table test1; TRUNCATE TABLE postgres=# select * from test1; f1 | f2 ----+---- (0 rows) postgres=# rollback; ROLLBACK postgres=# select * from test1; f1 | f2 ----+---- 1 | 1 2 | 2 (2 rows)
面白いのは、CREATE TABLE などもトランザクション内です。
postgres=# begin; BEGIN postgres=# create table test2 (f1 varchar(1), f2 int); CREATE TABLE postgres=# select * from test2; f1 | f2 ----+---- (0 rows) postgres=# rollback; ROLLBACK postgres=# select * from test2; ERROR: relation "test2" does not exist
当然、このトランザクションがコミットするまでは、 別のトランザクションからは test2 テーブルは見えません。
別のトランザクションが絡んでくると少しややこしくなります。
トランザクション A がトランザクション中にテーブルを作成しているときに 他のトランザクション B が同じテーブル名でテーブルを作成しようとすると トランザクション B は A の結果待ちになります。
トランザクション A がロールバックして テーブルの作成がキャンセルされた場合 トランザクション B がテーブルを作成できるので、 トランザクション B はトランザクションを継続できます。
しかし、トランザクション A がコミットして テーブルを作成が確定してしまった場合は、 トランザクション B はテーブルの作成ができないのため B 側は、次のエラーが発生します。
ERROR: duplicate key value violates unique constraint "pg_type_typname_nsp_index"
DROP TABLE も同様のことが起こります。
あまりこういったケースはないと思いますが、 この辺りの動きは Oracle と異なるので注意が必要です。
IE が Web サイトにアクセスすると 勝手に favicon.ico を探すので favicon.ico がないと Web サーバのエラーログに favicon.ico を探したログが残ってしまいます。
対処方法として favicon.ico へのアクセスをログに書き込まないように 設定するか、favicon.ico を実際に設置する方法があります。
後者の方法で、ダミー用の透明な favicon.ico が 欲しかったので作ってみました。
必要があれば使ってください。
ただし、ブックマークに登録した場合、他のサイトが Web ブラウザのデフォルトのアイコンか、設置されている favicon.ico が 表示されている中で、自分のところだけ空欄になって表示されるので 違和感は、かなりあります。
sudo コマンドを使用するときに パスワードを聞かれないようにする設定のメモです。
sudo の設定ファイルは /etc/sudoers ですが 編集するときは、直接開くのではなく visudo というコマンドを使用します。
ALL ALL=(ALL) NOPASSWD: ALL
左から、ユーザ、ホスト、権限、コマンドなのですが、 コマンドに NOPASSWD: と付けることでパスワードが聞かれなくなります。
特定のユーザに対して 特定のコマンドのみを許可したい場合は 次のように記述します。
user1 ALL=(ALL) NOPASSWD: /etc/init.d/httpd
これで user1 は httpd の実行ができるようになります。
Linux 複数のテキストファイルの文字列を一括で 置換するためのシェルスクリプトを作ってみました。
#!/bin/bash # ========================================================== # 複数ファイル一括置換コマンド # ----------------------------------------------------- # create : 2010/01/21 Studio ODIN # update : # ========================================================== # --- init --------------------------------------------- COMMAND_NAME=bulk_replace CUR_DIR=`pwd` # -- args ---------------------------------------------- TARGET_WORD=$1 REPLACE_WORD=$2 TARGET_DIR=$3 # -- args check ---------------------------------------- if [ "$TARGET_WORD" = "" ]; then echo "target word is nothing." >&2 echo "Usage: $0 targetword replaceword [targetpath]" >&2 exit 1 fi if [ "$REPLACE_WORD" = "" ]; then echo "replace word is nothing." >&2 echo "Usage: $0 targetword replaceword [targetpath]" >&2 exit 1 fi if [ "$TARGET_DIR" = "" ]; then TARGET_DIR=. fi # -- execute ------------------------------------------- grep -R -l "${TARGET_WORD}" "${TARGET_DIR}" | while read file do tfile=`mktemp -u` cp -f -p $file $tfile > /dev/null 2>&1 if [ $? -eq 0 ]; then sed -e "s/${TARGET_WORD}/${REPLACE_WORD}/g" $file > $tfile if [ $? -ne 0 ]; then echo "Warning: failed write '$file'" fi mv -f $tfile $file > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "Warning: failed rewrite '$file'" rm -f $tfile > /dev/null 2>&1 fi else echo "Warning: failed copy '$file'" fi done # -- normal end ---------------------------------------- cd $CUR_DIR exit 0 # ========================================================== # shell end # location: /usr/local/bin/bulk_replace # ==========================================================
実行する場合は、パスの指定など大事なファイルが 大変なことにならないように気を付けてください。 (自己責任でお願いします)
こんなコマンドは、すでにあるような気もしますが 自分で処理を考えて作ってみるのは面白いと思います。
Ruby の認定試験を受ける後輩から Array#inject が わかりにくいという話を聞いたので 簡単にまとめてみたいと思います。
Array#inject は配列の値を合計したりするのに使える便利なメソッドです。
$ irb irb(main):001:0> [1,2,3,4].inject(0) { | sum, i | sum + i } => 10
内部的には次のような処理になります。
[1,2,3,4].inject(0) { | sum, i | sum + i } `-------, loop: 1 0, 1 0 + 1 ~~|~~ ,----------' loop: 2 1, 2 1 + 2 ~~|~~ ,----------' loop: 3 3, 3 3 + 3 ~~|~~ ,----------' loop: 4 6, 4 6 + 4 ~~|~~ `----> 出力
2つめのブロック引数には配列の値がはいるのですが 1つめのブロック引数には、前回のループの最後の処理結果が入ります。
1巡目 (loop:1) の1つめのブロック引数は、 前回の処理結果がないので、初期値として inject メソッドの引数が設定されます。
ブロック内をわかりやすく書くと次のようになります。
irb(main):001:0> [1,2,3,4].inject(0) { | sum, i | sum += i } => 10
ここまでは簡単なのですが、この inject メソッドは 引数を省略することができます。 この場合の動きが要注意です。
上と同じ配列で試してみます。
irb(main):001:0> [1,2,3,4].inject { | sum, i | sum + i }
=> 10
結果は同じでした。
ここで、ブロック内の処理を変えてみます。
irb(main):001:0> [1,2,3,4].inject(0) { | sum, i | sum * i } => 0 irb(main):002:0> [1,2,3,4].inject { | sum, i | sum * i } => 24
まったく異なる結果になりました。
まず、引数がある場合の内部処理を見てみます。
[1,2,3,4].inject(0) { | sum, i | sum * i } `-------, loop: 1 0, 1 0 * 1 ~~|~~ ,----------' loop: 2 0, 2 0 * 2 ~~|~~ ,----------' loop: 3 0, 3 0 * 3 ~~|~~ ,----------' loop: 4 0, 4 0 * 4 ~~|~~ `----> 出力
次に、引数がない場合の内部処理を見てみます。
[1,2,3,4].inject { | sum, i | sum * i } `--------------------, loop: 1 1, 2 1 * 2 ~~|~~ ,----------' loop: 2 2, 3 2 * 3 ~~|~~ ,----------' loop: 3 6, 4 6 * 4 ~~|~~ `----> 出力
このように 初期値として 配列の 1つめの値が入っています。 また、1巡目 (loop:1) で 配列の 2つめの値が入っています。 ループの数も 1つ少なくなります。 引数を省略すると、 配列の 1つめのを値を初期値として利用するわけです。
つまり、次の 2つが等価となります。
irb(main):001:0> [1,2,3,4].inject(0) { | sum, i | sum * i } => 0 irb(main):002:0> [0,1,2,3,4].inject { | sum, i | sum * i } => 0
次のような PostgreSQL の SQL エラーがあります。
SELECT DISTINCT, ORDER BY expressions must appear in select list
これは SELECT DISTINCT を使用している場合に、 ORDER BY 句に含まれている項目が SELECT 句にない場合に発生します。
例えば、次のような SQL です。
SELECT DISTINCT field_1 , field_2 FROM test_table ORDER BY field_3
SELECT DISTINCT されているのは field_1 と field_2 ですが ソートは field_3 を指定しています。
これでは結果の並び順を保証することができないため エラーが発生するわけです。
ちなみに Oracle の場合は、次のようなエラーになります。
ORA-01791: SELECT式が無効です
ただ、Oracle は さらに賢いようで、次のような場合はエラーになりません。 ( PostgreSQL はエラーになります)
SELECT DISTINCT field_1 , field_2 FROM test_table WHERE field_3 = '0' ORDER BY field_3
この場合は、field_3 が 1つに固定されるため、 "ソート指定なし" と同じ状態になるためエラーになりません。
Windows 環境に簡単に Ruby の実行環境を作るフリーソフトが紹介されていたので 試しにインストールしてみました。
Windowsでスクリプト言語“Ruby”を導入するための和製インストーラー「Rumix」
まず、以下のサイトから Rumix をダウンロードします。
Rumix - Ruby Starter Package with Installer
これを書いている時点では「 Rumix 1.00(通常版)」「 Rumix 1.00(ruby 1.9.1版) 」と ありますが、どちらが良いかわからない人は「 Rumix 1.00(通常版)」を落としましょう。
ダウロードしたファイルを解凍して、その中の rumix_install.exe を実行します。
「次へ」ボタンを押します。
「次へ」ボタンを押します。
「次へ」ボタンを押します。
「次へ」ボタンを押します。
「次へ」ボタンを押します。
「次へ」ボタンを押します。
「次へ」ボタンを押します。
「インストール」ボタンを押します。
終わるのを待ちます。
待ちます。
待ちます。
これでインストールは終了です。
次に ruby スクリプトを作って実行させてみます。
デスクトップに test.rb というファイルを作って テキストエディタで スクリプトを書きます。
puts 'hello world!'
スタートメニューから
「 NYACUS (コマンドラインシェル) 」を起動します。
[d:\] $
NYACUS は Linux のシェルの操作ができる便利なツールです。
cd や ls, pwd などのコマンドも使えます。 ウィンドウにドラッグ&ドロップしてパスを指定することもできます。
[d:\] $ cd d:\desktop [d:\desktop] $ pwd d:\desktop
先ほど書いたスクリプトを実行させてみます。
"ruby test.rb" でも 直接指定でも実行させることができます。
簡単に ruby のスクリプトを実行できるので Ruby の試験勉強などにも とても役に立ちます。
Excel のマクロなど UTF-8 で出力する モジュールを紹介します。
PostgreSQL の テーブルレイアウトを Excel で作成して Excel のマクロで CREATE 文を生成しているのですが コメント文など 日本語を UTF-8 で出力するのに 利用させてもらいました。
使い方も簡単で、ダウンロードした class ファイルを Excel にインポートして、Open メソッドの代わりに 次のように記述します。
Dim f1 As New TextFile f1.FileCreate "test1.txt", "UTF-8" f1.TextWrite "このファイルは UTF-8 でエンコードされています。" f1.FileClose
Linux で realpath などが入っていない状況で 相対パスから絶対パスを取得するための シェルスクリプトです。
#!/bin/bash # ========================================================== # 絶対パス取得コマンド # ----------------------------------------------------- # create : 2010/01/07 Studio ODIN # update : # ========================================================== # --- init --------------------------------------------- COMMAND_NAME=fullpath CUR_DIR=`pwd` # -- args ---------------------------------------------- TARGET_OBJECT=$1 # -- args check ---------------------------------------- if [ "$TARGET_OBJECT" = "" ]; then pwd exit 0 fi if [ ! -e "$TARGET_OBJECT" ]; then echo "Error: '$TARGET_OBJECT' is not exists." >&2 exit 1 fi # -- get full path (is directory) ---------------------- if [ -d $TARGET_OBJECT ]; then cd $TARGET_OBJECT pwd exit 0 fi # -- get full path (is not directory) ------------------ cd `dirname $TARGET_OBJECT` TARGET_PATH=`pwd` TARGET_NAME=`basename $TARGET_OBJECT` if [ "$TARGET_PATH" = "/" ]; then echo $TARGET_PATH$TARGET_NAME else echo $TARGET_PATH/$TARGET_NAME fi # -- normal end ---------------------------------------- cd $CUR_DIR exit 0 # ========================================================== # shell end # location: /usr/local/bin/fullpath # ==========================================================
次の例は、fullpath という名前で /usr/local/bin に作成して実行権限を付けています。 環境に合わせて変更してください。
# cd /usr/local/bin # vi fullpath # chmod 755 fullpath
引数を指定しなければ、カレントディレクトリのパス、 ディレクトリやファイルを指定すれば、その絶対パスを返します。
$ fullpath /home/odin $ fullpath ../ /home $ fullpath / / $ fullpath ../../vmlinuz /vmlinuz
久々に「特集ネタ」を追加しました。