ぱと隊長日誌

ブログ運用もエンジニアとしての生き方も模索中

Oracle Database の LNNVL を PostgreSQL で実現する

Oracle Database には LNNVL というファンクションがあります。

LNNVL(condition)

LNNVL の説明を Oracle Database 12c R2 マニュアルから引用します。

LNNVLは、条件のオペランドの1つまたは両方がNULLの可能性がある場合にその条件を簡単に評価する方法を提供します。このファンクションは問合せのWHERE句で、またはWHEN条件として検索CASE式で使用できます。このファンクションは、引数として条件を取り、その条件がFALSEまたはUNKNOWNの場合はTRUEを戻し、TRUEの場合はFALSEを戻します。LNNVLは、スカラー式を指定できる場所であればどこでも指定でき、有効ではないが、発生する可能性があるNULLを評価するためにIS [NOT] NULL、ANDまたはOR条件が必要であるようなコンテキストでも指定できます。

(中略)

a = 2およびb=NULLの場合のLNNVLからの戻り値を次の表に示します。

条件 条件の真偽 LNNVLの戻り値
a = 1 FALSE TRUE
a = 2 TRUE FALSE
a IS NULL FALSE TRUE
b = 1 UNKNOWN TRUE
b IS NULL TRUE FALSE
a = b UNKNOWN TRUE
LNNVL

LNNVL の条件(condition)と戻り値を真理値表で整理します。

条件 戻り値
FALSE TRUE
TRUE FALSE
UNKNOWN TRUE

PostgreSQL には LNNVL に相当する関数が用意されていませんが、COALESCE と NOT を組み合わせることで、同じことを表現することができます。

COALESCE(NOT(condition), TRUE)

これが Oracle のマニュアルに記載の LNNVL の振る舞いと同等であることを PostgreSQL 10.3 で確認しました。

Linux のディレクトリとファイルのパーミッション組み合わせと振る舞い

パーミッションとその組み合わせ

Linuxディレクトリとファイルのパーミッションが組み合わさった時、どうふるまうのかを確認します。

ディレクトリ・ファイル単体

Linuxディレクトリ・ファイルのパーミッション表記で使用される文字は以下の定義がされています。

ファイル ディレクト
“R”読み(4) ファイルの内容を表示 ディレクトリ内のリスト表示
“W”書き(2) ファイルの上書き、変更 ディレクトリ内にファイル作成、削除
“X”実行(1) 実行ファイルの実行 そのディレクトリに移動
ファイルのパーミッション設定、ディレクトリは要注意 | VPSサーバーでWebサイト公開 備忘録 ~Linux、MySQLからAJAXまで

w権限で「ファイルの作成・削除」はディレクトリに、「ファイルの上書き・変更」はファイルに権限付与されることにご注意ください。

ディレクトリと子ディレクトリの関係

ディレクトリとファイルの関係

  • ファイルの操作を行うためには、ルートディレクトリ~ファイルの存在するディレクトリまでのx権限が必要となります。
    • 以降に挙げる全ての操作の前提となります。
  • ファイルの内容を表示するにはファイルのr権限が必要となります。
  • ファイルの上書き・変更にはファイルのw権限が必要となります。
    • ファイルをエディタなどで編集・保存する際はr権限も必要となります。
  • 実行ファイルの実行にはファイルのrx権限が必要となります。

まとめ

ディレクトリとその中のファイル操作することを想定したパーミッション設定をまとめます。これらをベースに必要最小限の権限のみを設定しましょう。

◎ルートディレクトリ~親ディレクト

rx権限(リスト表示・移動)を設定します。

◎子ディレクト

rx権限(リスト表示・移動)を設定します。

ディレクトリ内のファイル作成/削除があればw権限(ファイル作成・削除)も設定します。この時、ルートディレクトリ~親ディレクトリにw権限を設定する必要はありません。

◎ファイル

読み取りのみ:r権限
読み書きする:rw権限
実行する:rx権限(+必要に応じてw権限)

検証結果

今回の検証では設定するパーミッションにちなんだ名前をディレクトリ・ファイルに付けました。

名前 パーミッション
none ---
x --x
w -w-
wx -wx
r r--
rx r-x
rw rw-
rwx or all rwx

ディレクトリと子ディレクトリの関係

ディレクトリと子(サブ)ディレクトリにそれぞれパーミッションが設定された時、子ディレクトリ内でどのような操作が可能かを確認します。

操作 コマンド
ディレクトリ内のリスト表示 ls /all/{updir}/{dir}
ディレクトリ内にファイル作成・削除 touch /all/{updir}/{dir}/a.txt
そのディレクトリに移動 cd /all/{updir}/{dir}

{updir}:親ディレクト
{dir}:子ディレクト
a.txtは事前に存在しない。

ディレクトリのx権限有無でlsコマンドの実行結果がどのように変わるかを示します。
ディレクトリのx権限がないと、リスト表示はできますがアクセス許可がないというエラーが発生します。

$ ls /all/x/r
ls: /all/x/r/none にアクセスできません: 許可がありません
ls: /all/x/r/r にアクセスできません: 許可がありません
ls: /all/x/r/rw にアクセスできません: 許可がありません
ls: /all/x/r/rwx にアクセスできません: 許可がありません
ls: /all/x/r/rx にアクセスできません: 許可がありません
ls: /all/x/r/w にアクセスできません: 許可がありません
ls: /all/x/r/wx にアクセスできません: 許可がありません
ls: /all/x/r/x にアクセスできません: 許可がありません
none  r  rw  rwx  rx  w  wx  x
$ ls /all/x/rx
none  r  rw  rwx  rx  w  wx  x

検証結果を一覧にして示します。"OK"が操作可能です。

updir dir 表示(ls) 作成、削除(touch) 移動(cd)
none none
none x
none w
none wx
none r
none rx
none rw
none rwx
x none
x x OK
x w
x wx OK OK
x r OK
x rx OK OK
x rw OK
x rwx OK OK OK
w none
w x
w w
w wx
w r
w rx
w rw
w rwx
wx none
wx x OK
wx w
wx wx OK OK
wx r OK
wx rx OK OK
wx rw OK
wx rwx OK OK OK
r none
r x
r w
r wx
r r
r rx
r rw
r rwx
rx none
rx x OK
rx w
rx wx OK OK
rx r OK
rx rx OK OK
rx rw OK
rx rwx OK OK OK
rw none
rw x
rw w
rw wx
rw r
rw rx
rw rw
rw rwx
rwx none
rwx x OK
rwx w
rwx wx OK OK
rwx r OK
rwx rx OK OK
rwx rw OK
rwx rwx OK OK OK

ディレクトリとファイルの関係

ディレクトリとファイルにそれぞれパーミッションが設定された時、ファイルに対してどのような操作が可能かを確認します。

操作 コマンド
ファイルの内容を表示 cat /all/{dir}/{file}.sh
ファイルの上書き・変更 touch /all/{dir}/{file}.sh
実行ファイルの実行 /all/{dir}/{file}.sh

{dir}:ディレクト

{file}.shは以下の内容で事前に用意しました。

#!/bin/sh
echo "Hello, world!"

ディレクトリにx権限しかなく、ディレクトリ内のリスト表示ができなくても、ファイルを取り扱うことは可能です。

$ ls /all/x
ls: ディレクトリ /all/x を開くことが出来ません: 許可がありません
$ /all/x/rx.sh
Hello, world!

検証結果を一覧にして示します。"OK"が操作可能です。

dir file 表示(cat) 変更(touch) 実行(sh)
none none
none x
none w
none wx
none r
none rx
none rw
none rwx
x none
x x
x w OK
x wx OK
x r OK
x rx OK OK
x rw OK OK
x rwx OK OK OK
w none
w x
w w
w wx
w r
w rx
w rw
w rwx
wx none
wx x
wx w OK
wx wx OK
wx r OK
wx rx OK OK
wx rw OK OK
wx rwx OK OK OK
r none
r x
r w
r wx
r r
r rx
r rw
r rwx
rx none
rx x
rx w OK
rx wx OK
rx r OK
rx rx OK OK
rx rw OK OK
rx rwx OK OK OK
rw none
rw x
rw w
rw wx
rw r
rw rx
rw rw
rw rwx
rwx none
rwx x
rwx w OK
rwx wx OK
rwx r OK
rwx rx OK OK
rwx rw OK OK
rwx rwx OK OK OK

エルブラン・セマンティクス(Herbrand Semantics)理解メモ

はじめに

データベースのトランザクション(特にスケジュール)の理論を勉強しようとすると、エルブラン・セマンティクス(Herbrand Semantics)の理解が必要となります。

Herbrand Semantics の解説は以下の本・章にあります。

Transactional Information Systems: Theory, Algorithms, and the Practice of Concurrency Control and Recovery (The Morgan Kaufmann Series in Data Management Systems)

Transactional Information Systems: Theory, Algorithms, and the Practice of Concurrency Control and Recovery (The Morgan Kaufmann Series in Data Management Systems)

該当章:3.5 Herbrand Semantics of Schedules

ですが、本が英語であることに加え、読み解くには数学の知識も必要となります。そこで、周辺知識を含めて理解していく過程をエントリにまとめることにしました。

解説

ここではトランザクションが失敗(ロールバック)することを考えません。

次のようなスケジュールsを仮定します。

  1. a step ri(x) ∈ s of a transaction ti ∈ trans(s) reads the value written by the last wj(x) ∈ s, j ≠ i, that occurs before ri(x);
  2. a step wi(x) ∈ s writes a new value that potentially depends on the values of all data items that ti has read from the database or from other transactions in active(s) ∪ commits(s) prior to wi(x).

ここでは以下のことを仮定しています。

  1. ri(x)は最後にwriteされた値xをreadする。
  2. wi(x)はそのトランザクションtiがwi(x)の前にreadした全ての値に依存している。

DEFINITION 3.3 Herbrand Semantics of Steps

Let s be a schedule. The Herbrand semantics Hs of steps ri(x), wi(x) ∈ op(s) is recursively defined as follows:

  1. Hs(ri(x)) := Hs(wj(x)), where wj(x), j ≠ i, is the last write operation on x in s before ri(x).
  2. Hs(wi(x)) := fix(Hs(ri(y1)),...,Hs(ri(ym))), where the ri(yj), 1 ≤ j ≤ m, represent all read operations of ti that occur in s before wi(x), and where fix is an uninterpreted m-ary function symbol.

Hs は Herbrand semantics のことです。

1. Hs(ri(x)) := Hs(wj(x))

Hs(ri(x)) を Hs(wj(x))と定義するということです。
参考:数学記号の表 - Wikipedia
ri(x) は wj(x) に等しい、つまり最後にwriteした値をreadする、ということです。

2. Hs(wi(x)) := fix(Hs(ri(y1)),...,Hs(ri(ym)))

"m-ary function"とは「m項関数」と呼ばれ、m個の引数をもつ関数のことです。

関数fixの"i"はトランザクションTiのこと、"x"は値xのことです。
関数fixの引数はトランザクションTiでwi(x)以前の全てのread操作のHsです。

ここでのポイントは read/write が m-ary function に変換可能ということにあります。

例えば、次のスケジュールを考えます。
s = r1(x)r2(y)w2(x)w1(y)c2c1

値x, yには初期値があるはずです。これをトランザクションt0が書き込んだものと仮定すれば、次のスケジュールになります。
s = w0(x)w0(y)c0r1(x)r2(y)w2(x)w1(y)c2c1

これを踏まえて以下の展開を行います。

s = w0(x)w0(y)c0r1(x)r2(y)w2(x)w1(y)c2c1

is as follows, where f0x() and f0y() are 0-ary functions (constants):

Hs(w0(x)) = f0x()
Hs(w0(y)) = f0y()
Hs(r1(x)) = Hs(w0(x)) = f0x()
Hs(r2(y)) = Hs(w0(y)) = f0y()
Hs(w2(x)) = f2x(Hs(r2(y)) = f2x(f0y())
Hs(w1(y)) = f1y(Hs(r1(x)) = f1y(f0x())

Herbrand semantics Hs を展開していくと、どのread/writeもf0x()/f0y()を含む関数の式に変換されます。つまり、read/writeを初期状態と関数の式で表現できたということであり、異なるスケジュールのトランザクションの各ステップ(read/write)が同じ結果となるかを数式で比較可能となります。Herbrand semantics で表現することの価値はここにあります。

具体例については以下の記事を参照ください。
Serializablitiyとは? 1. Final State Serializabilityについて - Qiita
Serializablitiyとは? 2. View Serializabilityについて - Qiita
Herbrand Semantics の式の表現は異なりますが、実現していることは同じです。

DEFINITION 3.4 Herbrand Universe

Let D = {x, y, z,...} be a (finite) set of data items (representing the data of the underlying data server(s)). For a transaction t, let op(t) denote the set of all steps of t. The Herbrand universe HU for transactions ti, i > 0, is the smallest set of symbols satisfying the following conditions:

  1. f0x() ∈ HU for each x ∈ D, where f0x is a 0-ary function symbol (i.e., a constant);
  2. if wi(x) ∈ op(ti), |{ri(y) | (∃y ∈ D) ri(y) <ti wi(x)}| = m, and if v1,..., vm ∈ HU, then fix(v1,...,vm) ∈ HU, where fix is an m-ary function symbol.

"{ri(y) | (∃y ∈ D) ri(y) <ti wi(x)}"は集合の内包的記法です。
{ (代表元) | (代表元の満たすべき条件)} です。例えば {x | x ∈ S, P(x)} は S の元のうち、命題 P(x) が真であるものすべてを集めた集合を意味しています。
参考:数学記号の表 - Wikipedia

また、集合Aの要素数は|A|で表現されます。例えば、A={1,2,3,4}, |A|=4です。
参考:集合の要素数

つまり、"|{ri(y) | (∃y ∈ D) ri(y) <ti wi(x)}| = m"とはTiがwi(x)の前にreadした回数をmとする、ということです。

これを踏まえて DEFINITION 3.4 をまとめると、

  1. f0xは0項関数で定数だ。
  2. fixはm項関数(m個の引数を持つ)で、mはTiがwi(x)の前にreadした回数に等しい。

となります。

2.でfixとwi(x)の関係がピンとこない場合は DEFINITION 3.3を再確認してください。下記の式で wi(x)の Herbrand Semantics は fixの関数で表現されることが示されています。
Hs(wi(x)) := fix(Hs(ri(y1)),...,Hs(ri(ym)))

DEFINITION 3.5 Schedule Semantics

The semantics of a schedule s is the mapping

H[s] : D → HU

defined by

H[s](x) := Hs(wi(x))

where wi(x) is the last operation from s writing x, for each x ∈ D.

"H[s] : D → HU"とは写像の表記です。

写像とは"f : A → B"の形で表現され、Aの要素が決まるとBの要素が決まる対応関係です。
"f(A) = B"のように、fはAを引数にとってBとなる、と考えるとわかりやすいかもしれません。
参考:写像とは

つまり、"H[s](x) := Hs(wi(x))"は "H[s](x)" がスケジュールsの値xの最終的な状態(最後のwrite操作)を Herbrand Semantics で表現する、ということを表しています。

s = w0(x)w0(y)c0r1(x)r2(y)w2(x)w1(y)c2c1

H[s](x) = Hs(w2(x)) = f2x(f0y())
H[s](y) = Hs(w1(y)) = f1y(f0x())
※引用に際して一部省略

この例でスケジュールsの値xに対する最後のwrite操作はw2(x)、値yに対する最後のwrite操作はw1(y)であり、H[s](x), H[s](y) は これらのwrite操作を Herbrand Semantics で表現するということです。