Skip to content

Latest commit

 

History

History
2005 lines (1511 loc) · 88.3 KB

scalar-expressions-and-types.md

File metadata and controls

2005 lines (1511 loc) · 88.3 KB

SQL実行計画表現におけるスカラー式とデータ型

この文書について

この文書では、SQL実行計画表現の内部に出現する、スカラー式とデータ型について検討する。

本内容は「 SQL実行計画表現における関係演算子 」に基づいている。

コンセプト

  • スカラー式の表現は木構造
    • 関係演算グラフとは異なり、単純な木構造のみ
  • スカラー式は静的型付け
    • 式の型はコンパイル時に定まり、式の評価結果は特定のデータ型に合致する
  • すべての実行計画表現で同じスカラー式のモデルを採用する
    • 論理、中間、ステップ実行計画のそれぞれで共通のモデルを利用する
    • ただし、特定の実行計画にのみ出現する式要素も存在する
  • 参照、型、関数はいずれも first class でない
    • コンパイル時に定められ、実行前に対象を静的に特定可能
  • 実行時のデータ型は単純に保つ
    • nullity をデータ型に含めない

スカラー式と評価

スカラー式は主に関係演算子の構成要素として出現し、列の値や述語の計算に利用する。 例えば、四則演算や値の大小の比較などがこれらに該当する。

実行時において、処理系はスカラー式を評価 (evaluation) することで式が表現する値 (value) を得ることができる。 また、スカラー式はその構成要素にスカラー式を再帰的に有する木構造をなしており、評価の際にも部分式を評価して値を得たうえで、それらの値を利用して式を再帰的に評価していく。

式を評価する際に、スカラー式は「列への参照」を行うことがある。 これは対象のスカラー式を含む関係演算子が現在処理中の「行」のデータを対象とするもので、その「列の参照」を評価した際に得られる値は、現在処理中の行に含まれる、指定の列の値となる。 このような、処理中の文脈によって評価結果が変わる変数を「コンテキスト変数」とよぶ。

コンテキスト変数

コンテキスト変数には以下の種類が存在する。

フレーム変数 ~ ユーザー定義関数のパラメータに関する変数。

ストリーム変数 ~ 関係演算子の現在処理中の行に含まれる変数。

ローカル変数 ~ 式中で定義され、式が終わると利用されなくなる一時変数。

外部変数 ~ プログラムの外で宣言された変数。

以下のようなものを含む。

システム変数 ~ データベースが提供する変数。

セッション変数 ~ 現在接続中のセッションが提供する変数。

プレースホルダー変数 ~ $1 などで示され、SQLの文を実行する前に実行エンジンに値が与えられる変数。

上記のストリーム変数について、実行時にそれぞれの関係演算子を処理する際に、実行エンジンは「現在注目している行」を明確に定める必要がある。 特に入力が二階のリレーションである場合、処理中の行に含まれるグループのメンバーを「行」として取り扱う必要がある。

また、いずれの変数においても、変数の値は式の途中で別の値に変化することはない。

データ型

スカラー式を実行時に評価すると値が得られるが、この値は式ごとにコンパイル時に定められたデータの種類でなければならない。 このようなデータの種類を「データ型」とよび、コンパイル時にすべての式に対してそれぞれ定められる。

また、あるスカラー式が部分式を有する場合、それらの部分式のデータ型は対象のスカラー式が受け入れ可能でなければならない。 そうでない場合、対象のスカラー式はコンパイルに失敗する。

特殊値

スカラー式を評価する際に、評価結果が本来のデータ型から乖離した「特殊値 (special value)」になる場合がある。 特殊値には以下のものが含まれる。

NULL ~ 「値が存在しない」ことを表す

NOT A NUMBER ~ ゼロ除算などの結果に出現する「非数」を表す

なお、特殊値でない値のことを区別する場合、「正常値 (normal value)」とよぶことにする。

本モデルでは、正常値も特殊値も同様に値として取り扱うことにする。 また、データ型は正常値がとる範囲について規定し、あらゆるデータ型の式であっても、評価結果が特殊値になりるものとする。

実行時に利用しないデータ型

データ型の一部は、スカラー式のデータ型として直接利用されないものも含んでいる。

スカラー式のデータ型以外に、以下のデータ型が存在する。

  • 未解決型
    • 未解決の外部変数に対して一時的に付与される型
  • エラー型
    • データ型の解決に失敗したことを表す型

上記はいずれもスカラー式のデータ型としては出現しない。

データ型の表記

データ型を以下のように表記する。

データ型名 ~ データ型の概要

  • パラメーター
    • パラメータ名 - パラメータの概要
  • 特性
    • invariants, note, ...

なお、「パラメータ名」の末尾には以下の数量子を付与する場合がある。

  • ? 0個または1個
  • * 0個以上
  • + 1個以上

基本型

基本型は、それ以上に分解できないデータに与えられる型である。 ただし、一般的にアトムと分類しない「文字列」や「日付と時刻」等についても、利便性のために基本型として取り扱っている。

boolean ~ 真偽値

  • パラメーター
    • なし
  • 特性
    • 「述語」を表現するスカラー式は、このデータ型である必要がある

int ~ 符号付き整数

  • パラメーター
    • width - オクテット数の幅 (1, 2, 4, 8 のいずれか)
  • 特性
    • width={1,2} は演算にはほとんど利用しないため、内部表現を width=4 としてもよさそう

decimal ~ 固定小数点数

  • パラメーター
    • precision? - 整数部と小数部の桁数の和 (10進数)
    • scale? - 小数部の桁数 (10進数)
  • 特性
    • precision が未指定の場合、システムに定められた最大の桁数が指定されたものとみなす
    • scale が未指定の場合、小数点以下はその値によって適切な桁数に定まる
    • scale が指定されている場合、 0 <= scale <= precision でなければならない

float ~ 浮動小数点数

  • パラメーター
    • width - オクテット数の幅 (4, 8 のいずれか)
  • 特性
    • IEEE 754 の符号化形式を想定しているが、各演算は厳密でなくてもよい

character ~ 固定長文字列

  • パラメーター
    • length - 文字列の長さ
    • national - UTF-8を利用するかどうか
  • 特性
    • 既定の文字数に満たない文字列は何らかの文字でパディングされる

character varying ~ 可変長文字列

  • パラメーター
    • length? - 文字列の長さ
      • 未指定の場合、システムに定められた最大長の文字列を利用可能
  • 特性
    • なし

bit ~ 固定長ビット列

  • パラメーター
    • length - ビット数
  • 特性
    • 既定のビット数に満たないビット列は何らかの値でパディングされる

bit varying ~ 可変長ビット列 (最大長の制限あり)

  • パラメーター
    • length? - ビット数
      • 未指定の場合、システムに定められた最大長のビット列を利用可能
  • 特性
    • なし

octet ~ 固定長オクテット列

  • パラメーター
    • length - オクテット数
  • 特性
    • 既定のオクテット数に満たないオクテット列は何らかの値でパディングされる

octet varying ~ 可変長オクテット列 (最大長の制限あり)

  • パラメーター
    • length? - オクテット数
      • 未指定の場合、システムに定められた最大長のオクテット列を利用可能
  • 特性
    • なし

date ~ 日付

  • パラメーター
    • なし
  • 特性
    • 時刻は付与されない

time_of_day ~ 時刻

  • パラメーター
    • with_offset - オフセット情報を有するかどうか
  • 特性
    • なし

time_point ~ 日時

  • パラメーター
    • with_offset - オフセット情報を有するかどうか
  • 特性
    • なし

datetime_interval ~ 時間間隔

  • パラメーター
    • なし
  • 特性
    • 以下の3種類のフィールドからなる
      • month field - 月を元としたフィールド
      • day field - 日を元としたフィールド
      • time field - 秒を元としたフィールド
    • フィールド間で桁上がりは行われない

notes:

  • character で文字列の長さが満たない場合、現状は常に padding される前提
    • 等価比較を行う場合、 padding も一致しない限り同値にならない

複合型

複合型は、データ型を要素に持つような型である。

array ~ 配列

  • パラメータ
    • type - 要素型
    • length? - 要素数
      • 未指定の場合、要素数は不明
  • 特性
    • なし

record ~ レコード

  • パラメータ
    • fields+ - フィールドの一覧
      • name - フィールド名
      • type - データ型
  • 特性
    • なし

ユーザー定義型

ユーザー定義型は、アトム型や複合型にユーザーが名前を付けた型である。 データの表現は元の型と同一であるが、多重定義された演算を解決するためにモデルとして導入する。

なお、ユーザー定義型は実行時には出現せず、元のデータ型として取り扱われる。

コンパイラ合成型

これまでに説明したデータ型以外に、ユーザーが直接指定することができない種類のデータ型が存在する。

unknown ~ NULL リテラルの型

  • パラメータ
    • なし
  • 特性
    • 常に特殊値をとり、正常値が存在しない
    • あらゆる型に変換可能
    • 列の型やキャスト対象の型として指定できない

row_reference ~ テーブル上の行への参照

  • パラメータ
    • table - 対象のテーブル識別子
  • 特性
    • 疑似型で、テーブル上の行への参照を表す
      • TBD: 実行前に解決するかどうか

row_id ~ 行ID

  • パラメータ
    • series - 行IDを定義した要素の識別子
  • 特性
    • コンピューター上の表現は実行エンジンが決める
    • series が異なる2つの行IDは比較不可能
      • 複数の関係演算グラフ上で、 series が衝突する場合がある

error ~ コンパイルエラー

  • パラメータ
    • 未定
  • 特性
    • 実行時には出現しない

型変換

いくつかのスカラー式は、その部分式のデータ型によって「多重定義 (overload)」されている。 例えば、整数同士の加算と、固定小数点数同士の加算は、同じ加算に関するスカラー式としてあらわされるものの、実行時には異なる方法で処理する必要がある。

ここで、すべてのデータ型についてスカラー式の多重定義を行うのは現実的ではない。 そのため、スカラー式の処理を行う前に「型変換 type conversion」を行って型の種類や組み合わせの種類を削減したうえで、削減後のデータ型に対して多重定義を行うものとする。

なお、実行時においてこれらの変換が 暗黙に 行われることはいくつかの例外を除いて存在しない。 代わりに、後述の「キャスト変換」を明示的に行うスカラー式を挿入する。

以降では、それぞれの型変換について紹介する。


notes:

  • 現在はSQLの変換規則よりもかなり厳しめになっている

型分類

いくつかのデータ型は、上位の型分類 (type category) に属している。 型分類は実行時には特に出現しないが、スカラー式の多重定義を解決する上で重要な指標となる。

型分類には以下の種類が存在する。

真偽値型分類 (boolean type category) ~ 真偽値に分類されるデータ型の分類

  • boolean
  • unknown

数値型分類 (numeric type category) ~ 数値に分類されるデータ型の分類

  • int
  • decimal
  • float
  • unknown

文字列型分類 (character string type category) ~ 文字列に分類されるデータ型の分類

  • character
  • character varying
  • unknown

ビット列型分類 (bit string type category) ~ ビット列に分類されるデータ型の分類

  • bit
  • bit varying
  • unknown

オクテット列型分類 (octet string type category) ~ オクテット列に分類されるデータ型の分類

  • octet
  • octet varying
  • unknown

時間型分類 (temporal type category) ~ 時間を表すデータ型の分類

  • date
  • time_of_day
  • time_point
  • unknown

時間間隔型分類 (time interval type category) ~ 時間間隔を表すデータ型の分類

  • datetime_interval
  • unknown

コレクション型分類 (collection type category) ~ コレクションを表すデータ型の分類

  • array
  • unknown

構造体型分類 (structure type category) ~ 構造体を表すデータ型の分類

  • record
  • unknown

恒等変換

恒等変換 (identity conversion) は式のデータ型を、同じデータ型に変換する。

実際の挙動は「なにもしない」ということと同じであるが、変換規則を簡略化するために導入している。

単項真偽値昇格

単項真偽値昇格 (unary truth-value promotion) は真偽値型分類の単項演算を行う際に、演算に適したデータ型に変換する。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

変換元 変換先
boolean boolean
unknown boolean

二項真偽値昇格

二項真偽値昇格 (binary truth-value promotion) は特定の真偽値型分類の二項演算を行う際に、それぞれの真偽値を同じ種類のデータ型にそろえるための型変換である。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。 ただし、「左のデータ型と上のデータ型を二項真偽値昇格する場合に、左のデータ型がどのデータ型になるか」を表している。

boolean unknown
boolean boolean boolean
unknown boolean boolean

単項数値昇格

単項数値昇格 (unary numeric promotion) は数値型分類の単項演算を行う際に、演算に適したデータ型に変換する。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

変換元 変換先
int1 int4
int2 int4
int4 int4
int8 int8
decimal(p,s) decimal(p,s)
float4 float4
float8 float8
unknown int4

二項数値昇格

二項数値昇格 (binary numeric promotion) は特定の数値型分類の二項演算を行う際に、それぞれの数値を同じ種類のデータ型にそろえるための型変換である。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。 ただし、「左のデータ型と上のデータ型を二項数値昇格する場合に、左のデータ型がどのデータ型になるか」を表している。

int1 int2 int4 int8 decimal float4 float8 unknown
int1 int4 int4 int4 int8 decimal(3) float4 float8 int4
int2 int4 int4 int4 int8 decimal(5) float4 float8 int4
int4 int4 int4 int4 int8 decimal(10) float8 float8 int4
int8 int8 int8 int8 int8 decimal(19) float8 float8 int8
decimal(*,*) decimal(*,*) decimal(*,*) decimal(*,*) decimal(*,*) decimal(*,*) float8 float8 decimal(p,s)
float4 float4 float4 float8 float8 float8 float8 float8 float4
float8 float8 float8 float8 float8 float8 float8 float8 float8
unknown int4 int4 int4 int8 decimal(0, 0) float4 float8 int4

notes:

  • decimal の精度等の情報は、計算の過程で無視される
  • tiny/small int に対する二項演算は存在しない

単項文字列昇格

単項文字列昇格 (unary character string promotion) は文字列型分類の単項演算を行う際に、演算に適したデータ型に変換する。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

変換元 変換先
character(n) character varying(n)
character varying(n) character varying(n)
unknown character varying(0)

なお、変換の前後で文字列のエンコーディングは変化しない。


notes:

  • character の比較時にpaddingを行う場合、上記の規則ではうまくいかない

二項文字列昇格

二項文字列昇格 (binary character string promotion) は特定の文字列型分類の二項演算を行う際に、それぞれの文字列を同じ種類のデータ型にそろえるための型変換である。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。 ただし、「左のデータ型と上のデータ型を二項文字列昇格する場合に、左のデータ型がどのデータ型になるか」を表している。

character(m) character varying(m) unknown
character(n) character varying(n') character varying(n') character varying(n)
character varying(n) character varying(n') character varying(n') character varying(n)
unknown character varying(0) character varying(0) character varying(0)

また、二項で文字列のエンコーディング方式が同じである場合、元のエンコーディングを利用する。 そうでなく、エンコーディングが異なる場合、エンコーディングを強制的に UTF-8 に設定する。 上記の n' はエンコーディングが変化した際に、元のエンコーディングにおける n と「同じ文字数」の値を表す。

単項ビット列昇格

単項ビット列昇格 (unary bit string promotion) はビット列型分類の単項演算を行う際に、演算に適したデータ型に変換する。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

変換元 変換先
bit(n) bit varying(n)
bit varying(n) bit varying(n)
unknown bit varying(0)

二項ビット列昇格

二項ビット列昇格 (binary bit string promotion) はビット列型分類の二項演算を行う際に、それぞれのビット列を同じ種類のデータ型にそろえるための型変換である。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。 ただし、「左のデータ型と上のデータ型を二項ビット列昇格する場合に、左のデータ型がどのデータ型になるか」を表している。

bit(m) bit varying(m) unknown
bit(n) bit varying(n) bit varying(n) bit varying(n)
bit varying(n) bit varying(n) bit varying(n) bit varying(n)
unknown bit varying(0) bit varying(0) bit varying(0)

単項オクテット列昇格

単項オクテット列昇格 (unary octet string promotion) はオクテット列型分類の単項演算を行う際に、演算に適したデータ型に変換する。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

変換元 変換先
octet(n) octet varying(n)
octet varying(n) octet varying(n)
unknown octet varying(0)

二項オクテット列昇格

二項オクテット列昇格 (binary octet string promotion) はオクテット列型分類の二項演算を行う際に、それぞれのオクテット列を同じ種類のデータ型にそろえるための型変換である。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。 ただし、「左のデータ型と上のデータ型を二項オクテット列昇格する場合に、左のデータ型がどのデータ型になるか」を表している。

octet(m) octet varying(m) unknown
octet(n) octet varying(n) octet varying(n) octet varying(n)
octet varying(n) octet varying(n) octet varying(n) octet varying(n)
unknown octet varying(0) octet varying(0) octet varying(0)

単項時間昇格

単項時間昇格 (unary temporal promotion) は時間型分類の単項演算を行う際に、演算に適したデータ型に変換する。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

変換元 変換先
date date
time_of_day time_of_day
time_point time_point
unknown time_point

なお、昇格時にそれぞれの time_zone プロパティは失われない。 unknown から昇格した際には、 time_zone プロパティの指定がないものとして扱う。

二項時間昇格

二項時間昇格 (binary temporal promotion) は特定の時間型分類の二項演算を行う際に、それぞれの時間を同じ種類のデータ型にそろえるための型変換である。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。 ただし、「左のデータ型と上のデータ型を二項時間昇格する場合に、左のデータ型がどのデータ型になるか」を表している。

date time_of_day(z') time_point(z') unknown
date date time_point(z') time_point(z') date
time_of_day(z) time_point(z) time_of_day(z'') time_point(z'') time_of_day(z)
time_point(z) time_point(z) time_point(z'') time_point(z'') time_point(z)
unknown date time_of_day(z') time_point(z') time_point()

なお、タイムゾーンを表す z'' は次のように計算する。

  • z, z' のいずれもタイムゾーンを利用しない - z'' はタイムゾーンを利用しない
  • z, z' のいずれかがタイムゾーンを利用する - z'' はタイムゾーンを利用する
    • タイムゾーンを利用しない値 (ローカルタイム) は、ローカルタイムをシステムのタイムゾーンが付与された時間とみなした値に変換する
      • 例: システムのタイムゾーン +9:00 である場合、ローカルタイム 2001-01-01 00:00:002001-01-01 00:00:00+9:00 に変換される

単項時間間隔昇格

単項時間間隔昇格 (unary time interval promotion) は時間間隔型分類の単項演算を行う際に、演算に適したデータ型に変換する。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

変換元 変換先
time_interval datetime_interval
unknown datetime_interval

二項時間間隔昇格

二項時間間隔昇格 (binary time interval promotion) は特定の時間間隔型分類の二項演算を行う際に、それぞれの時間間隔を同じ種類のデータ型にそろえるための型変換である。

それぞれの項のデータ型に対する、型変換後のデータ型は以下のとおりである。

datetime_interval unknown
datetime_interval datetime_interval datetime_interval
unknown datetime_interval datetime_interval

単一化変換

単一化変換 (type unification) は複数のデータ型を単一のデータ型に変換する。

データ型 t{1}, .., t{n} について、以下のように単一化変換を行う。

  • n = 1 のとき
    • t{1}unknown の場合、unknownt{1}' とする
    • t{1} が真偽値型分類の場合、 t{1} に単項真偽値昇格を適用した型を t{1}' とする
    • t{1} が数値型分類の場合、 t{1} に単項数値昇格を適用した型を t{1}' とする
    • t{1} が文字列型分類の場合、 t{1} に単項文字列昇格を適用した型を t{1}' とする
    • t{1} がビット列型分類の場合、 t{1} に単項ビット列昇格を適用した型を t{1}' とする
    • t{1} がオクテット列型分類の場合、 t{1} に単項オクテット列昇格を適用した型を t{1}' とする
    • t{1} が時間型分類の場合、 t{1} に単項時間昇格を適用した型を t{1}' とする
    • t{1} が時間間隔型分類の場合、 t{1} に単項時間間隔昇格を適用した型を t{1}' とする
    • それ以外の場合、 t{1} に恒等変換を適用した型を t{1}' とする
  • n > 1 のとき, t{i} (i = 2, .., n) について:
    • t{i-1}', t{i} がいずれも unknown の場合、 unknownt{i}' とする
    • t{i-1}', t{i} がいずれも真偽値型分類の場合、 t{i-1}', t{i} に二項数値昇格を適用した型を t{i}' とする
    • t{i-1}', t{i} がいずれも数値型分類の場合、 t{i-1}', t{i} に二項数値昇格を適用した型を t{i}' とする
    • t{i-1}', t{i} がいずれも文字列型分類の場合、 t{i-1}', t{i} に二項文字列昇格を適用した型を t{i}' とする
    • t{i-1}', t{i} がいずれもビット列型分類の場合、 t{i-1}', t{i} に二項ビット列昇格を適用した型を t{i}' とする
    • t{i-1}', t{i} がいずれもオクテット列型分類の場合、 t{i-1}', t{i} に二項オクテット列昇格を適用した型を t{i}' とする
    • t{i-1}', t{i} がいずれも時間型分類の場合、 t{i-1}', t{i} に二項時間昇格を適用した型を t{i}' とする
    • t{i-1}', t{i} がいずれも時間間隔型分類の場合、 t{i-1}', t{i} に二項時間間隔昇格を適用した型を t{i}' とする
    • 上記以外で、 t{i-1}t{i} が同一の型である場合、 t{i} に恒等変換を適用した結果を t{i}' とする
    • それ以外の場合、型変換に失敗する

上記の操作を行った結果の t{n}' が型変換の結果の型となる。


notes:

  • 単に単項・二項昇格で畳み込むだけ

代入変換

代入変換 (assignment conversion) は、特定の部分式を宛先変数の型に変換する。

代入変換が可能な型の組み合わせは以下のとおりである。

from \ to boolean int1 int2 int4 int8 decimal float4 float8 character character varying bit bit varying octet octet varying date time_of_day time_point datetime_interval array record
boolean v - - - - - - - - - - - - - - - - - - -
int1 - v v v v D v v - - - - - - - - - - - -
int2 - D v v v D v v - - - - - - - - - - - -
int4 - D D v v D v v - - - - - - - - - - - -
int8 - D D D v D v v - - - - - - - - - - - -
decimal - D D D D D v v - - - - - - - - - - - -
float4 - - - - - - v v - - - - - - - - - - - -
float8 - - - - - - v v - - - - - - - - - - - -
character - - - - - - - - D D - - - - - - - - - -
character varying - - - - - - - - D D - - - - - - - - - -
bit - - - - - - - - - - D D - - - - - - - -
bit varying - - - - - - - - - - D D - - - - - - - -
octet - - - - - - - - - - - - D D - - - - - -
octet varying - - - - - - - - - - - - D D - - - - - -
date - - - - - - - - - - - - - - v - v - - -
time_of_day - - - - - - - - - - - - - - - v v - - -
time_point - - - - - - - - - - - - - - D D v - - -
datetime_interval - - - - - - - - - - - - - - - - - v - -
array - - - - - - - - - - - - - - - - - - 1 -
record - - - - - - - - - - - - - - - - - - - 2
unknown v v v v v v v v v v v v v v v v v v v v

上記の凡例は以下のとおりである。

  • v - 常に変換可能
  • D - 変換可能だが、実行時に実行エラーになる場合がある
  • - - 変換不可能
  • 1 - 要素型まで同一の場合のみ変換可能で、実行時に実行エラーになる場合がある
  • 2 - 同一のレコード型のみ変換可能

代入変換を行うのは、主に以下の操作である。

  • 関数呼び出しで実引数の型を仮引数の型へ変換
  • トランザクションエンジン上の値と比較
  • トランザクションエンジン上に値を出力

ただし、精度が失われる場合の挙動は操作ごとに異なる。


notes:

定数変換

定数変換 (constant conversion) は、定数式を宛先変数の型に変換する。

定数変換は、何らかの型変換を行う際に、対象の式が定数式だった場合に適用される型変換である。

以下のパターンによってそれぞれ処理内容が異なる。

  • 文字列から文字列型分類以外への変換
  • 文字列以外から文字列型分類への変換
  • 配列から array 型への変換
  • 単一化変換
  • 代入変換

上記以外では、従来の規則によって型変換を行う。

リテラル変換

文字列型分類の定数式 C と、それを直接内包する式 E が存在し、かつ EC に文字列型分類以外のデータ型を要求している場合、要求する型に応じて以下の型変換を行う。

要求される型分類 キャスト変換先のデータ型
真偽値型分類 boolean
数値型分類 文字列の内容を「数値定数」として解釈
ビット列型分類 文字列の内容を「ビット列定数」として解釈
オクテット列型分類 文字列の内容を「オクテット列定数」として解釈
時間型分類 time_point
時間間隔型分類 datetime_interval
コレクション型分類 array

ただし、 E が多重定義されており、かつ要求される型分類が複数存在する場合、定数変換は行わない。 また、以下の型変換規則においては個別の定数変換の規則を適用する。

  • 単一化変換
  • 代入変換

このような変換を「リテラル変換」とよぶ。

文字列化変換

文字列型分類の定数式 C と、それを直接内包する式 E が存在し、かつ EC に文字列型分類のデータ型を要求している場合、 Ccharacter variant にキャスト変換する。

なお、 C の文字列を character variant 型に変換できない場合、定数変換は適用しない。

また、以下の型変換規則においては個別の定数変換の規則を適用する。

  • 単一化変換
  • 代入変換

定数配列変換

配列の定数式を array 型へ変換する場合、キャスト変換と同様に変換する。

なお、キャスト変換のあらゆる規則では array の要素型を型変換によって変更できない。

定数単一化変換

定数式を含む単一化変換は、以下の規則で行う。

  1. 単一化変換を適用し、適用できる場合にはその型をそのまま利用する
  2. そうでない場合、文字列型分類の定数式をすべて取り除き、それらのデータ型に対して単一化変換を適用する
    • 適用できた場合、適用結果のデータ型の型分類に基づき、対象の文字列定数式を指定の型分類へリテラル変換したのちに、再度全体に単一化変換を適用する
    • 適用できなかった場合、定数変換は適用しない

定数代入変換

定数式に代入変換を適用する場合、宛先のデータ型へキャスト変換を行う。

代入変換は精度低下の場合に実行エラーとなるが、定数式である場合にはそれを無視する。 なお、キャスト変換を行えない場合には定数変換を適用しない。

キャスト変換

キャスト変換 (casting conversion) は、 cast 式によってある式の結果を別のデータ型に明示的に変換する。

キャスト変換が可能な型の組み合わせは以下のとおりである。

from \ to boolean int1 int2 int4 int8 decimal float4 float8 character character varying bit bit varying octet octet varying date time_of_day time_point datetime_interval array record
boolean v - - - - - - - v v - - - - - - - - - -
int1 - v v v v v v v v v - - - - - - - - - -
int2 - v v v v v v v v v - - - - - - - - - -
int4 - v v v v v v v v v - - - - - - - - - -
int8 - v v v v v v v v v - - - - - - - - - -
decimal - v v v v v v v v v - - - - - - - - - -
float4 - D D D D D v v v v - - - - - - - - - -
float8 - D D D D D v v v v - - - - - - - - - -
character D D D D D D D D v v D D D D D D D D D D
character varying D D D D D D D D v v D D D D D D D D D D
bit - - - - - - - - v v v - - - - - - - - -
bit varying - - - - - - - - v v - v - - - - - - - -
octet - - - - - - - - v v - - v - - - - - - -
octet varying - - - - - - - - v v - - - v v - - - - -
date - - - - - - - - v v - - - v v - v - - -
time_of_day - - - - - - - - v v - - - - - v v - - -
time_point - - - - - - - - v v - - - - v v v - - -
datetime_interval - - - - - - - - v v - - - - - - - v - -
array - - - - - - - - v v - - - - - - - - 1 -
record - - - - - - - - v v - - - - - - - - - 2
unknown v v v v v v v v v v v v v v v v v v v v

上記の凡例は以下のとおりである。

  • v - 常に変換可能
  • D - 変換可能だが、実行時に実行エラーになる場合がある
  • - - 変換不可能
  • 1 - 要素型をキャスト変換可能な組み合わせのみ適用可能で、実行時に実行エラーになる場合がある
  • 2 - 同一のレコード型のみ変換可能

cast 式の評価については後に解説する。

拡大変換

拡大変換 (widening conversion) は、ある型を持つあらゆる式の値を、その情報を一切失わずに宛先変数の型へ安全に変換する。

拡大変換が可能な型の組み合わせは以下のとおりである。

from \ to boolean int1 int2 int4 int8 decimal float4 float8 character character varying bit bit varying octet octet varying date time_of_day time_point datetime_interval array record
boolean v - - - - - - - - - - - - - - - - - - -
int1 - v v v v 1 v v - - - - - - - - - - - -
int2 - - v v v 1 v v - - - - - - - - - - - -
int4 - - - v v 1 v v - - - - - - - - - - - -
int8 - - - - v 1 v v - - - - - - - - - - - -
decimal - - - - - 1 v v - - - - - - - - - - - -
float4 - - - - - - v v - - - - - - - - - - - -
float8 - - - - - - - v - - - - - - - - - - - -
character - - - - - - - - 2 2 - - - - - - - - - -
character varying - - - - - - - - - 2 - - - - - - - - - -
bit - - - - - - - - - - 2 2 - - - - - - - -
bit varying - - - - - - - - - - - 2 - - - - - - - -
octet - - - - - - - - - - - - 2 2 - - - - - -
octet varying - - - - - - - - - - - - - 2 - - - - - -
date - - - - - - - - - - - - - - v - v - - -
time_of_day - - - - - - - - - - - - - - - v v - - -
time_point - - - - - - - - - - - - - - - - v - - -
datetime_interval - - - - - - - - - - - - - - - - - v - -
array - - - - - - - - - - - - - - - - - - 3 -
record - - - - - - - - - - - - - - - - - - - 4
unknown v v v v v v v v v v v v - - v v v v v v

上記の凡例は以下のとおりである。

  • v - 常に変換可能
  • - - 変換不可能
  • 1 - 数値の精度が失われない場合のみ変換可能
  • 2 - 宛先の長さが変換元以上である場合のみ変換可能
  • 3 - 要素型が同一で、かつ宛先の長さが変換元以上である場合のみ変換可能
  • 4 - 同一のレコード型のみ変換可能

拡大変換は現在のところ関数のオーバーロード解決のみに利用される。

スカラー式の種類

本章では、スカラー式の具体的な種類について紹介する。

定数式

スカラー式の一部には、特定の部分式に「定数式 (constant expression)」のみを受け付けるものがある。

定数式とは、評価結果が常に同じ値になることが明らかなスカラー式のことで、関係演算子を実行することなく式の評価を行える。

本モデルでは、以下のいずれかを満たすスカラー式を定数式とみなす。

  1. immediate
  2. variable_reference のうち、参照先のコンテキスト変数に「定数」属性が付与されている
  3. 「定数式可」の特性を有し、かつすべての部分式が定数式であるもの

上記のうち、コンテキスト変数に「定数」属性が付与されるには、以下のいずれかを満たす必要がある。

  1. 外部変数のうち、実行前に参照可能であり、かつ常に同じ値を返す
  2. フレーム変数のうち、実行前に参照可能である
  3. ストリーム変数やローカル変数のうち、列を定義した際に定数式を束縛している

ただし、上記を満たしても何らかの理由で定数属性が付与されない可能性もある。

スカラー式が「定数式可」であるかどうかは、スカラー式の種類によって異なる。 例えば、「二項の加算」は「定数式可」ではあるが、「関数呼び出し」は対象の関数によって異なる。

なお、実行時には定数式はすべて immediate に置き換えられている。 つまり、「部分式が定数式であること」を要求する式は、実行時においては同部分式はかならず immediate 式であり、そうでない場合はコンパイルエラーとなり実行できない。

スカラー式の表記

スカラー式を以下のように表記する。

スカラー式名 ~ スカラー式の概要

  • パラメーター
    • パラメータ名 - パラメータの概要
  • 事前条件 - 部分式等に関する制限
  • 型変換 - 部分式に適用する型変換
  • 結果型 - 評価結果のデータ型
  • 評価概要 - 実行時に式を評価する手順の概要
  • 特性
    • その他の特性

なお、「パラメータ名」の末尾には以下の数量子を付与する場合がある。

  • ? 0個または1個
  • * 0個以上
  • + 1個以上

なお、スカラー式の分類は役割によってではなく、主にその構造によって定められている。

表記中には、同名で複数のスカラー式や、演算種 (operator_kind) の定義を記載する場合がる。 これは、部分式のデータ型によって多重定義が行われている場合である。

基本式

基本式 (primary expression) は部分式をとらない、不可分な式である。

immediate ~ 即値

  • パラメーター
    • value - 式を評価した結果を表す値
    • type - 式のデータ型
  • 事前条件 - なし
  • 型変換 - 恒等変換
  • 結果型 - type に指定されたデータ型
  • 評価概要 - value に相当する値
  • 特性
    • 常に定数式可
    • 基本的にはリテラルを表すが、定数式として解決済みのものがこの式に置き換えられるため、定数として取りうるすべての値が出現しうる

以下はSQLにおける標準的な定数と、そのデータ型である。

文字列定数 ~ シングルクウォートで囲んだ文字列。

文字列中にシングルクウォートを出現させる場合、シングルクウォートを二回重ねる。
また、バックスラッシュをエスケープシーケンスの開始文字として利用できる。

文字列定数は `character varying` として解釈される。
その `length` は対象の文字列を表すのに必要十分な値で、 `national` は `false` となる。

国際化文字列定数 ~ シングルクウォートで囲んだ文字列の先頭に文字 N を指定したもの。

基本的には文字列定数と同等の解釈だが、 `national` が `true` となる。

ビット列定数 ~ シングルクウォートで囲んだ文字列の先頭に文字 B を指定したもの。

文字列定数と同様だが、 `0` または `1` のみからなる文字列でなければならない。

ビット列定数は `bit varying` として解釈される。

オクテット列定数 ~ シングルクウォートで囲んだ文字列の先頭に文字 X を指定したもの。

文字列定数と同様だが、 `0-9`, `A-F`, または `a-f` の2文字の組が連続する文字列でなければならない。

オクテット列定数は `octet varying` として解釈される。

数値定数 ~ 数値を表す定数。

以下の種類がある。

1. 小数点および指数のいずれも含まない数値
   * `int(width=4)` に収まればそのデータ型
   * `int(width=4)` に収まらず、 `int(width=8)` に収まればそのデータ型
   * `int(width=8)` に収まらなければ、 `decimal` のうち必要十分な `precision` をもち、かつ `scale=0` のデータ型
2. 小数点または指数のいずれかまたは両方を含む数値
   * `decimal` のうち必要十分な `precision` と `scale` をもつデータ型

その他の定数 ~ そのほかの定数は、文字列を cast 式によって変換することで得られる。

`cast` 式については後述する。

variable_reference ~ 変数参照

  • パラメーター
    • reference - 参照先の変数を表す識別子
    • kind - 対象の変数の種類
  • 事前条件 - なし
  • 型変換 - 恒等変換
  • 結果型 - 参照先の変数の型
  • 評価概要 - 参照先の変数に格納された値
  • 特性
    • 対象の変数が定数である場合、定数式可

単項演算

単項演算 (unary operation) は部分式を一つだけとる式である。

unary ~ 単項演算

  • パラメーター
    • operator_kind - 演算の種類
    • operand - 被演算項

operator_kind の値によって式の処理内容が大きく異なる。 共通の性質を持つ operator_kind が多いため、まずは分類ごとの共通性質を紹介する。

算術演算 ~ 算術クラスの単項演算

* 事前条件 - `operand` が数値型分類であること
* 型変換 - 単項数値昇格
* 結果型 - 型変換の結果と同様
* 評価概要
  * 特殊値: 特殊値
* 特性
  * 定数式可

論理演算 ~ 論理クラスの単項関係

* 事前条件 - `operand` が真偽値型分類であること
* 型変換 - 単項真偽値昇格
* 結果型 - 型変換の結果と同様
* 評価概要
  * 特殊値: 特殊値
* 特性
  * 定数式可

時間間隔演算 ~ 時間間隔クラスの単項演算

* 事前条件 - `operand` が時間間隔型分類であること
* 型変換 - 単項数値昇格
* 結果型 - 型変換の結果と同様
* 評価概要
  * 特殊値: 特殊値
* 特性
  * 定数式可

null性判定 ~ null性判定クラスの単項関係

* 事前条件 - なし
* 型変換 - 恒等変換
* 結果型 - `boolean`
* 特性
  * 定数式可

真偽値判定 ~ true 判定

* 事前条件 - `operand` が真偽値型分類であること
* 型変換 - 単項真偽値昇格
* 結果型 - 型変換の結果と同様
* 特性
  * 定数式可

以下は operator_kind のとる値と、そのような unary の詳細である。 なお、「共通分類」に示される分類の性質を継承する。

plus ~ 単項プラス

* 共通分類 - 算術演算, 時間間隔演算
* 評価概要
  * 正常値: `operand` の評価結果と同等
* 特性
  * 実行時には短絡化してもよさそう

sign_inversion ~ 数値符号反転

* 共通分類 - 算術演算, 時間間隔演算
* 評価概要
  * 正常値: `operand` の符号反転
* 特性
  * `int` の最小値に対して実施すると実行エラー (overflow)

length ~ 文字列要素数

* 事前条件 - `operand` が文字列型分類であること
* 型変換 - 単項文字列昇格
* 結果型 - `int(width=4)`
* 評価概要
  * 正常値: 文字列が `national=false` なら文字列のオクテット数, そうでなければ文字列の文字数
  * 特殊値: 特殊値
* 特性
  * 定数式可

length ~ ビット列要素数

* 事前条件 - `operand` がビット列型分類であること
* 型変換 - 単項ビット列昇格
* 結果型 - `int(width=4)`
* 評価概要
  * 正常値: ビット列のビット数
  * 特殊値: 特殊値
* 特性
  * 定数式可

length ~ オクテット列要素数

* 事前条件 - `operand` がオクテット列型分類であること
* 型変換 - 単項オクテット列昇格
* 結果型 - `int(width=4)`
* 評価概要
  * 正常値: オクテット列のオクテット数
  * 特殊値: 特殊値
* 特性
  * 定数式可

conditional_not ~ 条件否定

* 共通分類 - 論理演算
* 評価概要
  * 正常値: `operand` の論理否定

is_null ~ null性判定

* 共通分類 - null性判定
* 評価概要
  * 正常値: `false`
  * 特殊値: `true`

is_true ~ true 判定

* 共通分類 - 真偽値判定
* 評価概要
  * 正常値: `operand` の値
  * 特殊値: `false`

is_false ~ false 判定

* 共通分類 - 真偽値判定
* 評価概要
  * 正常値: `operand` の値の否定
  * 特殊値: `false`

is_unknown ~ 特殊値判定

* 共通分類 - 真偽値判定
* 評価概要
  * 正常値: `false`
  * 特殊値: `true`
* 備考
  * `is_null` と同等だが、真偽値型のみに適用可能

cast ~ 型変換

  • パラメーター
    • type - 変換先のデータ型
    • loss_policy - 値の精度が失われる際の挙動
      • ignore - 精度低下を無視し変換を実行
      • floor - 元の値以上の最小の値に変換する
      • ceil - 元の値以下の最大の値に変換する
      • unknown - 特殊値を返す
      • warn - 警告を表示し変換を実行
      • error - 実行時エラー
    • operand - 変換元の式
  • 事前条件 - operand のデータ型から、 type へのキャスト変換が可能であること
  • 型変換 - type へのキャスト変換
  • 結果型 - キャスト変換の結果
  • 評価概要 - 後述。ただし「精度が失われる」場合の挙動は loss_policy の指定に準拠
  • 特性
    • 定数式可

cast 演算子の評価は、変換元のデータ型と変換後のデータ型の組み合わせによって決まる。 以下に可能な組み合わせごとの評価方法の概略を示す。

なお、 operand 部分式の評価結果を v 、そのデータ型を S, type が表す型を TS から T へのキャスト変換を S ~ T と表記する。 ただし、特殊値である場合には cast 式の評価結果は常に特殊値となる。

S = T ~ 変換元と変換後で同じデータ型の場合、評価結果は v となる。

数値型分類 ~ int ~ v の整数部のみを取り出し v' とする。 このとき、 v の小数部が 0 以外の場合は 精度が失われる

`v'` が `T` の表現可能な整数である場合、評価結果は `v'` となる。
そうでない場合、`T` の表現可能な整数のうち `v` に最も近いものが評価結果となり、**精度が失われる**。

`v` が `NaN` の場合は実行エラー (arithmetic error) となる。

数値型分類 ~ float ~ vT の表現可能な数値の最小値から最大値の範囲に収まっている場合、 v に近しい T の表現可能な数値 v' が式の評価結果となる。 そうでない場合、T の表現可能な数値のうち v' に最も近いものが評価結果となる (精度は失われない)。

なお、実際にどのような `v'` が選ばれるかはシステムに依存する。

int ~ decimal ~ vT の表現可能な要素である場合、 v が式の評価結果となる。 そうでない場合、T の表現可能な要素のうち v に最も近いものが評価結果となり、精度が失われる

float ~ decimal ~ vT の表現可能な数値の最小値から最大値の範囲に収まっている場合、 v に近しい T の表現可能な数値 v' が式の評価結果となる。 そうでない場合、T の表現可能な数値のうち v に最も近いものが評価結果となり、精度が失われる

`v` が `NaN` の場合は実行エラー (arithmetic error) となる。

なお、実際にどのような `v'` が選ばれるかはシステムに依存する。

decimal ~ decimal ~ vTscale に合わせて小数部を丸めたものを v' とする。 ただし、この丸め方はシステムによって定義される (TBD)。 丸めによって表現する値が変わる場合、 精度が失われる

`v'` が `T` の表現可能な数値の最小値から最大値の範囲に収まっている場合、 `v'` が式の評価結果となる。
そうでない場合、`T` の表現可能な数値のうち `v` に最も近いものが評価結果となり、**精度が失われる**。

character ~ character ~ 文字列を表す値 v に対し、 v の長さが Tlength と等しい場合、 v が式の評価結果となる。 v の長さが Tlength よりも小さい場合、 vTlength まで末尾にパディング文字を加えたものが式の評価結果となる。 v の長さが Tlength よりも大きい場合、 length 以下になるまで末尾からUTF-8文字を取り除き、その結果が length 未満の場合は length まで末尾にパディング文字を加えたものが式の評価結果となる。 取り除いた文字がパディング文字以外である場合、 精度が失われる

character ~ character variant ~ 文字列を表す値 v に対し、 v の長さが Tlength と等しいか小さい場合、 v が式の評価結果となる。 そうでない場合、 vTlength 以下になるまで末尾からUTF-8文字を取り除いたものが式の評価結果となる。 取り除いた文字がパディング文字以外である場合、 精度が失われる

character variant ~ character ~ 文字列を表す値 v に対し、 v の長さが Tlength と等しい場合、 v が式の評価結果となる。 v の長さが Tlength よりも小さい場合、 vTlength まで末尾にパディング文字を加えたものが式の評価結果となる。 v の長さが Tlength よりも大きい場合、 length 以下になるまで末尾からUTF-8文字を取り除き、その結果が length 未満の場合は length まで末尾にパディング文字を加えたものが式の評価結果となる。 取り除いた文字がパディング文字以外である場合、 精度が失われる

character variant ~ character variant ~ 文字列を表す値 v に対し、 v の長さが Tlength と等しいか小さい場合、 v が式の評価結果となる。 そうでない場合、 v から Tlength 以下になるまで末尾からUTF-8文字を取り除いたものが式の評価結果となる。

文字を取り除く場合、 **精度が失われる**。

bit ~ bit ~ ビット列を表す値 v に対し、 v の長さが Tlength と等しい場合、 v が式の評価結果となる。 v の長さが Tlength よりも小さい場合、 vTlength まで末尾にパディングビットを加えたものが式の評価結果となる。 v の長さが Tlength よりも大きい場合、 vTlength まで末尾からビットを取り除いたものが式の評価結果となる。 取り除いたビットがパディングビット以外である場合、 精度が失われる

bit ~ bit variant ~ ビット列を表す値 v に対し、 v の長さが Tlength と等しいか小さい場合、 v が式の評価結果となる。 そうでない場合、 vTlength まで末尾から文字を取り除いたものが式の評価結果となる。 取り除いたビットがパディングビット以外である場合、 精度が失われる

bit variant ~ bit ~ ビット列を表す値 v に対し、 v の長さが Tlength と等しい場合、 v が式の評価結果となる。 v の長さが Tlength よりも小さい場合、 vTlength まで末尾にパディングビットを加えたものが式の評価結果となる。 v の長さが Tlength よりも大きい場合、 vTlength まで末尾からビットを取り除いたものが式の評価結果となる。 取り除いたビットがパディングビット以外である場合、 精度が失われる

bit variant ~ bit variant ~ ビット列を表す値 v に対し、 v の長さが Tlength と等しいか小さい場合、 v が式の評価結果となる。 そうでない場合、 vTlength まで末尾から文字を取り除いたものが式の評価結果となる。 ビットを取り除く場合、 精度が失われる

octet ~ octet ~ オクテット列を表す値 v に対し、 v の長さが Tlength と等しい場合、 v が式の評価結果となる。 v の長さが Tlength よりも小さい場合、 vTlength まで末尾にパディングオクテットを加えたものが式の評価結果となる。 v の長さが Tlength よりも大きい場合、 vTlength まで末尾からオクテットを取り除いたものが式の評価結果となる。 取り除いたオクテットがパディングオクテット以外である場合、 精度が失われる

octet ~ octet variant ~ オクテット列を表す値 v に対し、 v の長さが Tlength と等しいか小さい場合、 v が式の評価結果となる。 そうでない場合、 vTlength まで末尾から文字を取り除いたものが式の評価結果となる。 取り除いたオクテットがパディングオクテット以外である場合、 精度が失われる

octet variant ~ octet ~ オクテット列を表す値 v に対し、 v の長さが Tlength と等しい場合、 v が式の評価結果となる。 v の長さが Tlength よりも小さい場合、 vTlength まで末尾にパディングオクテットを加えたものが式の評価結果となる。 v の長さが Tlength よりも大きい場合、 vTlength まで末尾からオクテットを取り除いたものが式の評価結果となる。 取り除いたオクテットがパディングオクテット以外である場合、 精度が失われる

octet variant ~ octet variant ~ オクテット列を表す値 v に対し、 v の長さが Tlength と等しいか小さい場合、 v が式の評価結果となる。 そうでない場合、 vTlength まで末尾から文字を取り除いたものが式の評価結果となる。 オクテットを取り除く場合、 精度が失われる

date ~ time_point ~ 日付を表す値 v に対し、 T の時計における v と同じ日付の 00:00:00.000 の日時を式の評価結果とする。

time_of_day ~ time_point ~ 時刻を表す値 v に対し、 T の時計における v と同じ時刻の 1970-01-01 の日時を式の評価結果とする。

time_point ~ date ~ 日時を表す値 v に対し、 T の時計における v の日付を式の評価結果とする。 T の時計における v の時刻が 00:00:00.000 以外の場合、 精度が失われる

time_point ~ time_of_day ~ 日時を表す値 v に対し、 T の時計における v の時刻を式の評価結果とする(T のタイムゾーンも引き継ぐ)。 T の時計における v の日付が 1970-01-01 以外の場合、 精度が失われる

array ~ array ~ S の要素型を Vs, v の要素数を Ns, T の要素型を Vt, T の最大要素数を Nt とおく。 また、 NsNt の小さいほうの値を N とおく。 なお、 N < Nt となる場合、 精度が失われる

`v` の1番目の要素から `N` 番目の要素について、それぞれ `Vs` ~ `Vt` のキャストを行った結果を `w` とおく。
式の結果は、 `w` の1番目から `N` 番目の要素からなる配列となる。

TBD: array length semantics

record ~ record ~ TBD

文字列型分類 ~ boolean ~ 文字列を表す v に対し、前後の空白文字を取り除き、英字アルファベットを小文字化したものを v' とする。

`v'` が文字列 "true" と一致するかまたはその1文字以上の接頭辞である場合、式の評価結果は `true` となる。

`v'` が文字列 "false" と一致するかまたはその1文字以上の接頭辞である場合、式の評価結果は `false` となる。

`v'` が上記のいずれにも該当しない場合、実行エラー (format error) となる。

文字列型分類 ~ 数値型分類 ~ 文字列を表す v に対し、前後の空白文字を取り除いたものを v' とする。

`v'` が数値を表す文字列である場合、その数値を表現可能な `decimal` を `S` とし、対応する数値を `v''` とする。
式の評価結果は、 `v''` に対して `S' ~ T` のキャストを行った結果となる。

`v'` が数値を表す文字列でない場合、実行エラー (format error) となる。

TBD: special values for floating point number

文字列型分類 ~ ビット列型分類 ~ 文字列を表す v に対し、前後の空白文字を取り除いたものを v' とする。

`v'` が文字 "0" または "1" の列からなる文字列である場合、そのようなビット列を表現可能な `bit varying` を `S` とし、対応する値を `v''` とする。
式の評価結果は、 `v''` に対して `S' ~ T` のキャストを行った結果となる。

`v'` がビット列を表す文字列でない場合、実行エラー (format error) となる。

文字列型分類 ~ オクテット列型分類 ~ 文字列を表す v に対し、前後の空白文字を取り除いたものを v' とする。

`v'` が文字集合 `[0-9A-Fa-f]` のいずれかの要素列からなる文字列である場合、そのようなオクテット列を表現可能な `octet varying` を `S` とし、対応する値を `v''` とする。
式の評価結果は、 `v''` に対して `S' ~ T` のキャストを行った結果となる。

`v'` がオクテット列を表す文字列でない場合、実行エラー (format error) となる。

文字列型分類 ~ 時間型分類 ~ 文字列を表す v に対し、前後の空白文字を取り除いたものを v' とする。

`v'` が日時を表す文字列である場合、対応する `time_point` の値を `v''` とする。
式の評価結果は、 `v''` に対して `time_point ~ T` のキャストを行った結果となる。

`v'` が時刻を表す文字列である場合、対応する `time_of_day` の値を `v''` とする。
式の評価結果は、 `v''` に対して `time_of_day ~ T` のキャストを行った結果となる。

`v'` が日付を表す文字列である場合、対応する `date` の値を `v''` とする。
式の評価結果は、 `v''` に対して `date ~ T` のキャストを行った結果となる。

`v'` が日時、時刻、日付のいずれを表す文字列でない場合や、後続のキャストに失敗した場合、実行エラー (format error) となる。

文字列型分類 ~ 時間間隔型分類 ~ TBD

文字列型分類 ~ 配列型分類 ~ TBD

文字列型分類 ~ 構造体型分類 ~ TBD

文字列型分類 以外 ~ 文字列型分類 ~ v の標準的な文字列表現を v' とする。 式の評価結果は、文字列 v' に対し character variant ~ T のキャストを行った結果となる。

二項演算

二項演算 (binary operation) は部分式を二つとる式である。

binary ~ 二項演算

  • パラメーター
    • operator_kind - 演算の種類
    • left - 左項
    • right - 右項

operator_kind の値によって式の処理内容が大きく異なる。 共通の性質を持つ operator_kind が多いため、まずは分類ごとの共通性質を紹介する。

算術演算 ~ 算術演算クラスの二項演算

以下の共通の性質を有する。

* 事前条件 - `left`, `right` がいずれも数値型分類であること
* 型変換 - 二項数値昇格
* 結果型 - 二項数値昇格の結果型によって異なる
  * `decimal` 以外 - 二項数値昇格の結果と同じ
* 評価概要
  * 二項のいずれかが特殊値: 特殊値
* 特性
  * 定数式可
  * TBD: それぞれ overflow について考える

文字列演算 ~ 文字列演算クラスの二項演算

以下の共通の性質を有する。

* 事前条件 - `left`, `right` がいずれも文字列型分類であること
* 型変換 - 二項文字列昇格
* 評価概要
  * 二項のいずれかが特殊値: 特殊値
* 特性
  * 定数式可

ビット列演算 ~ ビット列演算クラスの二項演算

以下の共通の性質を有する。

* 事前条件 - `left`, `right` がいずれもビット列型分類であること
* 型変換 - 二項ビット列昇格
* 評価概要
  * 二項のいずれかが特殊値: 特殊値
* 特性
  * 定数式可

オクテット列演算 ~ オクテット列演算クラスの二項演算

以下の共通の性質を有する。

* 事前条件 - `left`, `right` がいずれもオクテット列型分類であること
* 型変換 - 二項オクテット列昇格
* 評価概要
  * 二項のいずれかが特殊値: 特殊値
* 特性
  * 定数式可

配列演算 ~ 配列演算クラスの二項演算

以下の共通の性質を有する。

* 事前条件 - `left`, `right` がいずれも同一の `array` 型であること
* 型変換 - 恒等変換
* 評価概要
  * 二項のいずれかが特殊値: 特殊値
* 特性
  * 定数式可

論理演算 ~ 論理演算クラスの二項演算

以下の共通の性質を有する。

* 事前条件 - `left`, `right` がいずれも真偽値型分類であること
* 型変換 - 二項真偽値昇格
* 結果型 - `boolean`
* 評価概要
* 特性
  * 定数式可

以下は operator_kind のとる値と、そのような binary の詳細である。 なお、「共通分類」に示される分類の性質を継承する。

add ~ 算術和

* 共通分類 - 算術演算
* 結果型
  * `left:decimal(p, s)', 'right:decimal(q, t)` - `decimal(max(p-s, q-t) + max(s,t) + 1, max(s,t))`
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の算術和

add ~ 時間の和

* 事前条件 - `left` が時間型分類であり、 `right` が時間間隔型分類であること、またはその逆
* 型変換 - 時間型分類を単項時間昇格, 時間間隔型分類を単項時間間隔昇格
* 結果型 - 時間型分類の昇格後の結果
* 評価概要
  * いずれも正常値: 時間に時間間隔を足した結果
  * いずれかが特殊値: 特殊値
* 特性
  * 定数式可
  * TBD: interval に time field がある場合、 date も time_point にすべき?

add ~ 時間間隔の和

* 事前条件 - `left`, `right` が時間間隔型分類である
* 型変換 - 二項時間間隔昇格
* 結果型 - 型昇格の結果
* 評価概要
  * いずれも正常値: 時間間隔の和
  * いずれかが特殊値: 特殊値
* 特性
  * 定数式可

subtract ~ 算術差

* 共通分類 - 算術演算
* 結果型 - 二項数値昇格の結果型によって異なる
  * `left:decimal(p, s)', 'right:decimal(q, t)` - `decimal(max(p-s, q-t) + max(s,t) + 1, max(s,t))`
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の算術差

subtract ~ 時間の差

* 事前条件 - `left` が時間型分類であり、 `right` が時間間隔型分類である
* 型変換 - `left` を単項時間昇格, `right` を単項時間間隔昇格
* 結果型 - `datetime_interval`
* 評価概要
  * いずれも正常値: `left` から `right` を引いた結果
  * いずれかが特殊値: 特殊値
* 特性
  * 定数式可
  * 結果は必ず *day-time interval* となり、 year-month field は 0 になる

subtract ~ 時間間隔の差

* 事前条件 - `left`, `right` が時間間隔型分類である
* 型変換 - 二項時間間隔昇格
* 結果型 - 型昇格の結果
* 評価概要
  * いずれも正常値: 時間間隔の差
  * いずれかが特殊値: 特殊値
* 特性
  * 定数式可

multiply ~ 算術積

* 共通分類 - 算術演算
* 結果型 - 二項数値昇格の結果型によって異なる
  * `left:decimal(p, s)', 'right:decimal(q, t)` - `decimal(p + q, s + t)`
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の算術積

multiply ~ 時間間隔のスカラー積

* 事前条件 - `left` が数値型分類であり、 `right` が時間間隔型分類であること、またはその逆
* 型変換 - 数値型分類を単項時間昇格, 時間間隔型分類を単項時間間隔昇格
* 結果型 - `datetime_interval`
* 評価概要
  * いずれも正常値: スカラー値と時間間隔の積
  * いずれかが特殊値: 特殊値
* 特性
  * 定数式可

divide ~ 算術商

* 共通分類 - 算術演算
* 結果型 - 二項数値昇格の結果型によって異なる
  * `left:decimal(p, s)', 'right:decimal(q, t)` - `decimal(p + q, s + t)`
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の算術商
* 特性
  * `right` が `0` の場合、実行エラー (divide by zero) となる

divide ~ 時間間隔のスカラー商

* 事前条件 - `left` が時間間隔型分類であり、 `right` が数値型分類であること
* 型変換 - `left` を単項時間間隔昇格, `right` を単項時間昇格
* 結果型 - `datetime_interval`
* 評価概要
  * いずれも正常値: 時間間隔の商
  * いずれかが特殊値: 特殊値
* 特性
  * 定数式可

remainder ~ 算術剰余

* 共通分類 - 算術演算
* 結果型 - 二項数値昇格の結果型によって異なる
  * `left:decimal(p, s)', 'right:decimal(q, t)` - `decimal(p + q, s + t)`
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の算術剰余
* 特性
  * `right` が `0` の場合、実行エラー (divide by zero) となる

concat ~ 文字列連接

* 共通分類 - 文字列演算
* 結果型 - 型変換の結果で、かつ `length` がそれぞれの文字列型の長さの和
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の連接
* 特性
  * なし

concat ~ ビット列連接

* 共通分類 - ビット列演算
* 結果型 - 型変換の結果で、かつ `length` がそれぞれのビット列型の長さの和
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の連接
* 特性
  * なし

concat ~ オクテット列連接

* 共通分類 - オクテット列演算
* 結果型 - 型変換の結果で、かつ `length` がそれぞれのオクテット列型の長さの和
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の連接
* 特性
  * なし

concat ~ 配列連接

* 共通分類 - 配列演算
* 結果型 - 型変換の結果で、かつ `length` がそれぞれの `array` の長さの和
* 評価概要
  * 二項がいずれも正常値: `left`, `right` の連接
* 特性
  * なし

conditional_and ~ 条件論理積

* 共通分類 - 論理演算
* 評価概要
  * `left`, `right` のどちらも `true` - `true`
  * `left`, `right` のいずれかが `false` - `false`
  * それ以外 - 特殊値
* 特性
  * 定数式可
  * 短絡化可能

conditional_or ~ 条件論理和

* 共通分類 - 論理演算
* 評価概要
  * `left`, `right` のいずれかが `true` - `true`
  * `left`, `right` のどちらも `false` - `false`
  * それ以外 - 特殊値
* 特性
  * 定数式可
  * 短絡化可能

compare ~ 比較演算

  • 事前条件 - left, right が下記の型変換を行える組み合わせであること
  • パラメーター
    • compare_kind - 比較の種類 (後述)
    • left - 左項
    • right - 右項
    • collation_ref? - 照合方式への参照
  • 型変換 - 単一化変換
  • 結果型 - boolean
  • 評価概要
    • 二項がいずれも正常値: 後述
    • 二項のいずれかが特殊値: 特殊値
  • 特性
    • 定数式可
    • 比較は collation_ref に指定された照合方式で行う

以下は利用可能な compare_kind の種類である。

equal ~ 等価比較

* 評価概要
  * 二項がいずれも正常値: `left`, `right` が等価なら `true`, それ以外は `false`

not_equal ~ equal の論理否定

* 評価概要
  * 二項がいずれも正常値: `left`, `right` が等価なら `false`, それ以外は `true`

less ~ 順序比較 (より小さい)

* 評価概要
  * 二項がいずれも正常値: `left` が `right` より小さいなら `true`, それ以外は `false`

less_equal ~ 順序比較 (以下)

* 評価概要
  * 二項がいずれも正常値: `left` が `right` より小さいか等価なら `true`, それ以外は `false`

greater ~ 順序比較 (より大きい)

* 評価概要
  * 二項がいずれも正常値: `left` が `right` より大きいなら `true`, それ以外は `false`

greater_equal ~ 順序比較 (以上)

* 評価概要
  * 二項がいずれも正常値: `left` が `right` より大きいか等価なら `true`, それ以外は `false`

複雑な式

match ~ パターン照合

  • パラメーター
    • match_kind - 照合の種類
      • like - LIKE 照合
      • similar - SIMILAR TO 照合
    • input - 照合される値
    • pattern - 照合パターン
    • escape - 照合パターンのエスケープ文字
  • 事前条件 - match, pattern, escape がいずれも文字列型分類であること
  • 型変換 - match, pattern, escape をそれぞれ単一化変換
  • 結果型 - boolean
  • 評価概要
    • match, pattern, escape のいずれかが特殊値である場合: 特殊値
    • escape が 2 characters 以上の場合: 特殊値
    • 上記以外の場合:
      1. pattern の文字列を match_kind の方式で解釈し、評価器 R を計算する
        • このとき escape の文字 c があれば c をエスケープ文字として pattern 文字列を解釈する
        • pattern 文字列が妥当でない場合、特殊値を式の結果とする
      2. R を文字列 match に適用し、 match が適合したら true, そうでなければ false を式の結果のとする
  • 特性
    • 定数式可

conditional ~ 条件式

  • パラメーター
    • alternatives+ - 条件の一覧
      • condition - 条件式
      • body - 条件が成立する場合に評価する式
    • default_expression? - いずれも条件が成立しない場合に評価する式
  • 事前条件
    • alternatives.condition は真偽値型分類であること
    • default_expression が存在しない場合、 alternatives.body は単一化変換を行えること
    • default_expression が存在する場合、 alternatives.bodydefault_expression は単一化変換を行えること
  • 型変換
    • 条件部
      • alternatives.condition をそれぞれ単項真偽値昇格
    • 結果部
      • default_expression がない場合 - alternatives.body の単一化変換
      • default_expression がある場合 - alternatives.body, default_expression の単一化変換
  • 結果型 - 型変換の結果
  • 評価概要
    • alternatives.conditiontrue となるもののうち、初めに出現するものに対応する alternatives.body の評価結果
    • alternatives.conditiontrue となるものがなく、かつ default_expression が存在する - default_expression の評価結果
    • alternatives.conditiontrue となるものがなく、かつ default_expression が存在しない - 特殊値
  • 特性
    • 定数式可
    • 部分式の評価を短絡化する

coalesce ~ 最初の正常値を返す

  • パラメーター
    • alternatives+ - 式の一覧
  • 事前条件 - alternatives は単一化変換を行えること
  • 型変換 - 単一化変換
  • 結果型 - 型変換の結果
  • 評価概要
    • alternatives の評価結果が正常値であるもののうち、初めに出現するものを評価結果とする
    • 上記ですべてが特殊値の場合、結果も特殊値
  • 特性
    • 定数式可
    • 部分式の評価を短絡化する

let ~ ローカル変数を利用した式

  • パラメーター
    • variables - 定義するローカル変数の一覧
      • define - 定義するローカル変数の識別子
      • value - 束縛する式
    • body - 定義したローカル変数を利用する式
  • 事前条件 - なし
  • 型変換 - 恒等変換
  • 結果型 - body のデータ型と同一
  • 評価概要 - variables.value をそれぞれ評価し、対応する variables.define に束縛する。その後、 body を評価した結果を全体の評価結果とする
  • 特性
    • 定数式可
    • variables.value の評価時には、それよりも手前の variables.define の変数を参照できる

function_call ~ 関数呼び出し

  • パラメーター
    • reference - 呼び出し先の関数識別子
    • arguments* - 引数の一覧
  • 事前条件
    • 個々の arguments から対応する関数の仮引数のデータ型へ代入変換が可能
  • 型変換
    • 個々の arguments を対応する関数の仮引数のデータ型に代入変換
      • ただし、精度が失われる場合にはエラーを出力する (loss_policy=error)
  • 結果型 - 関数の戻り値のデータ型
  • 評価概要
    • arguments をそれぞれ評価し、 reference の関数の引数として関数を呼び出し、関数の戻り値を結果とする
  • 特性
    • reference が intrinsic であり、かつ定数可であれば定数式可
    • 基本的に正格評価

複合型に関する式

array_construct ~ 配列の要素を参照

  • パラメーター
    • type - 構築する配列型
    • elements* - 要素を表す式
  • 事前条件 - type が配列型であり、かつ elements のデータ型がそれぞれ type の要素型に代入変換可能であること
  • 型変換 - elements のデータ型をそれぞれ type の要素型に代入変換
  • 結果型 - type
  • 評価概要
    • elements を要素に持つ配列を評価結果とする
      • elements に特殊値が含まれている場合、配列上のその位置の値を特殊値とする (TBD)
  • 特性
    • なし

array_length ~ 配列要素数

  • パラメーター
    • value - 配列式
  • 事前条件 - valuearray 型であること
  • 型変換 - 恒等変換
  • 結果型 - int(width=4)
  • 評価概要
    • 正常値: 配列の要素数
    • 特殊値: 特殊値
  • 特性
    • 定数式可

array_get ~ 配列の要素を参照

  • パラメーター
    • value - 配列式
    • position - 要素の位置
  • 事前条件 - value が配列型かつ、 positionint
  • 型変換 - value を恒等変換, position を単項数値昇格
  • 結果型 - value のデータ型の要素型
  • 評価概要
    • value が正常値: value のうち position が指す要素
      • ただし範囲外の場合は特殊値
    • value が特殊値: 特殊値
  • 特性
    • position は 1 origin

array_compare_quantification ~ 配列量化比較

  • パラメーター
    • compare_kind - 比較の種類
    • quantifier - 量化子
      • all - 全量化
      • any - 存在量化
    • left - 比較される式
    • right - 配列式
    • collation_ref? - 照合方式への参照
  • 事前条件 - right が配列型かつ、下記の型変換が可能
  • 型変換 - left の型と、 array の要素型を単一化変換
  • 結果型 - boolean
  • 評価概要
    • leftright のそれぞれの要素について compare_kind, collation_ref の組み合わせで compare 式と同等の評価を行う
      • quantifier=all の場合:
        • すべての評価結果が true - true
        • いずれかの評価結果が false - false
        • それ以外 - 特殊値
      • quantifier=any の場合:
        • すべての評価結果が false - false
        • いずれかの評価結果が true - true
        • それ以外 - 特殊値
  • 特性
    • 実行時に cast の明示化ができなさそう(やると高そう)なので、演算子内で実現する必要がありそう

record_construct ~ 配列の要素を参照

  • パラメーター
    • type - 構築するレコード型
    • fields* - フィールドの一覧
      • field_ref - フィールド参照
      • value - フィールドの値
  • 事前条件 - typerecord 型であり、かつそれぞれの fields.value のデータ型が type 上の対応するフィールド fields.ref のデータ型に代入変換可能
  • 型変換 - それぞれの fields.value のデータ型を type 上の対応するフィールド fields.ref のデータ型に代入変換
  • 結果型 - type
  • 評価概要 - fields からなるレコード
  • 特性
    • なし

record_get ~ レコードの要素を参照

  • パラメーター
    • value - レコード式
    • field_ref - フィールド参照
  • 事前条件 - valuerecord
  • 型変換 - 恒等変換
  • 結果型 - value のデータ型に含まれる field_ref のデータ型
  • 評価概要
    • value が正常値: value のうち field_ref が指し示す値
    • value が特殊値: 特殊値
  • 特性
    • フィールド参照が間違っている場合、そもそもコンパイルできない

副問合せ式

副問合せ式 (sub-query expression) は、副問合せを含む式である。 論理実行計画にのみ出現し、以降では正規化により除去される。

副問合せを含む式は、それぞれ query プロパティに副問合せを表現する関係演算グラフを保持している。 また、この関係演算グラフは必ず単一の emit 演算子を含んでいる。

なお、スカラー式が内包する関係演算グラフは、内部で同スカラー式が参照可能なコンテキスト変数を参照可能である。

subquery_scalar ~ スカラー副問合せ

  • パラメーター
    • query - 副問合せ
  • 事前条件 - 副問合せの emit が単一の列を出力する
  • 型変換 - query の出力列の型を恒等変換
  • 結果型 - 副問合せの emit が出力する列の型
  • 評価概要
    • query の問い合わせを実行し、問合せ結果のリレーションを U とおく
      • U 0行である場合: 特殊値
      • U 1行である場合: その行の唯一の列の値を評価結果とする
      • U 2行以上である場合: 実行エラー (too many sub-query rows)
  • 特性
    • 実行時には出現しない

subquery_exists ~ 存在量化副問合せ

  • パラメーター
    • query - 副問合せ
  • 事前条件 - なし
  • 型変換 - なし
  • 結果型 - boolean
  • 評価概要
    • query の問い合わせを実行し、問合せ結果のリレーションを U とおく
      • U 0行である場合: false
      • U 1行以上である場合: true
  • 特性
    • 実行時には出現しない

subquery_compare_quantification ~ 量化比較副問合せ

  • パラメーター
    • compare_kind - 比較演算子
    • quantifier - 量化子
      • all - 全量化
      • any - 存在量化
    • left - 比較される式
    • query - 副問合せ
    • collation_ref? - 照合方式への参照
  • 事前条件
    • 副問合せの emit が単一の列を出力する
    • 下記の型変換が可能
  • 型変換 - left の型と、 query の出力列の型を単一化変換
  • 結果型 - boolean
  • 評価概要
    • query の問い合わせを実行し、問合せ結果の出力列をそれぞれ right とおき、 left とそれぞれの right, compare_kind, collation_ref の組み合わせで compare 式と同等の評価を行う
      • quantifier=all の場合:
        • すべての評価結果が true - true
        • いずれかの評価結果が false - false
        • それ以外 - 特殊値
      • quantifier=any の場合:
        • すべての評価結果が false - false
        • いずれかの評価結果が true - true
        • それ以外 - 特殊値
  • 特性
    • 実行時には出現しない

その他の話題

  • character *, bit *length を実行時情報とするかどうか
    • テーブルに保存する際には上記は必須だが、実行時表現を考えるとこれらはデータ内に埋め込んでしまってもよさそう
    • variant のみという手もあるが、現状は実行時にはほぼ variant にしてから演算している
  • decimalprecisionscale を実行時情報とするかどうか
    • 上記と同様
  • array の最大長をやめる?
    • 上記と同様