メタデータを指定する

最初の少し長めの節では、データベースや SDO モデルについて表したメタデータが、リレーショナル DAS からどのように返されるのかを説明します。

リレーショナル DAS のコンストラクタが実行される際に、 情報を受け取る必要があります。この情報は、 コンストラクタへの最初の引数として連想配列で渡します。 これにより、リレーショナル DAS に対して、 必要なデータベース情報を伝えます。 テーブル名、カラム、主キーや外部キーの情報がここに含まれます。 必要な内容を理解することはきわめて簡単でしょう。 一度書いてしまえば、それを PHP ファイルに保存して 必要に応じてインクルードすることができます。 コンストラクタの二番目、三番目の引数として、リレーショナル DAS がオブジェクト間の関連やデータグラフの形式を知るために必要な情報を渡します。 これによって、最終的にデータベースのデータをグラフに正規化する方法が決まります。

データベースのメタデータ

コンストラクタに対する最初の引数で、対象となる リレーショナルデータベースを定義します。

各テーブルは、最大で 4 つのキーからなる連想配列で表されます。

キー
name テーブルの名前。
columns カラムの名前を含んだ配列。順不同。
PK 主キーとなるカラムの名前。
FK ふたつのエントリ 'from' および 'to' からなる配列で、 外部キーを含むカラムおよび外部キーが参照するテーブルを指定します。 テーブルに外部キーが存在しない場合には 'FK' を指定する必要はありません。指定できる外部キーの数は ひとつだけです。また、外部キーが参照する先は、 そのテーブルの主キーでなければなりません。

<?php
/*****************************************************************
* データベースを定義するメタデータ
******************************************************************/
$company_table = array (
  
'name' => 'company',
  
'columns' => array('id''name',  'employee_of_the_month'),
  
'PK' => 'id',
  
'FK' => array (
      
'from' => 'employee_of_the_month',
      
'to' => 'employee',
      ),
  );
$department_table = array (
  
'name' => 'department'
  
'columns' => array('id''name''location''number''co_id'),
  
'PK' => 'id',
  
'FK' => array (
      
'from' => 'co_id',
      
'to' => 'company',
      )
  );
$employee_table = array (
  
'name' => 'employee',
  
'columns' => array('id''name''SN''manager''dept_id'),
  
'PK' => 'id',
  
'FK' => array (
      
'from' => 'dept_id',
      
'to' => 'department',
      )
  );
$database_metadata = array($company_table$department_table$employee_table);
?>

このメタデータに対応するリレーショナルデータベースは、 例えば MySQL の場合は以下のように定義されます。

create table company (
 id integer auto_increment,
 name char(20),
 employee_of_the_month integer,
 primary key(id)
);
create table department (
 id integer auto_increment,
 name char(20),
 location char(10),
 number integer(3),
 co_id integer,
 primary key(id)
);
create table employee (
 id integer auto_increment,
 name char(20),
 SN char(4),
 manager tinyint(1),
 dept_id integer,
 primary key(id)
);

あるいは DB2 なら以下のようになります。

create table company ( \
  id integer not null generated by default as identity,  \
  name varchar(20), \
  employee_of_the_month integer, \
  primary key(id) )
create table department ( \
  id integer not null generated by default as identity, \
  name varchar(20), \
  location varchar(10), \
  number integer, \
  co_id integer, \
  primary key(id) )
create table employee ( \
  id integer not null generated by default as identity, \
  name varchar(20), \
  SN char(4), \
  manager smallint, \
  dept_id integer, \
  primary key(id) )

この例ではデータベースに外部キーが定義されておらず、 データベースには参照整合性が強制されていません。しかし、 department テーブルの co_id カラム および employee テーブルの dept_id カラムは、 それぞれ company あるいは department レコードの主キーを含むように 意図されています。そのため、これらの 2 つのカラムは外部キーのように動作します。

この例には 3 つめの外部キーがあります。それは company レコードの employee_of_the_month カラムが employee テーブルのひとつの行をさすというものです。この外部キーと、 その他の 2 つのキーとの違いに注意しましょう。 employee_of_the_month カラムは単一の値をとる関係を表します。ある会社には、 「今月の従業員」はひとりしか存在しえません。 co_id および dept_id は複数の値をとる関係を表します。会社には多くの部署がありますし、 ひとつの部署には多くの従業員が属しています。 この差は、 メタデータの残りの部分で company-department および department-employee の関係を包含関係として扱う時に明らかになります。

データベースのメタデータを作成する際に従わなければならない規則は 以下のとおりです。

  • すべてのテーブルには主キーが存在し、その主キーがメタデータで 指定されている必要があります。主キーがなければ、オブジェクトの 一意性を確保することができません。テーブルを作成する SQL 文を見てわかるように、主キーは自動生成することができます。 つまり、レコードが挿入される際に自動で値が設定されるということです。 この場合、自動生成された主キーはデータベースから取得可能で、 データベースに行が追加されると、すぐにデータオブジェクトに反映されます。

  • データベースに存在するすべてのカラムについてメタデータで記述する必要はありません。 実際に使用するものだけを指定します。例えば、company テーブルの中に SDO 経由でのアクセスを必要としないカラムがある場合、そのカラムを メタデータに記述する必要はありません。一方、それを記述したとしても 何の問題もありません。アプリケーションから値を取得したり代入したり することがなければ、未使用のカラムを記述していても何の影響も及ぼしません。

  • データベースのメタデータで、外部キーの指し示す先として カラム名ではなくテーブル名が指定されていることにお気づきでしょう。 厳密に言えば、リレーショナルモデルでは 主キー以外を対象とした外部キーを指定することも可能です。 しかし、SDO モデルを作成する際に使用できるのは 主キーを対象とした外部キーだけなので、 メタデータではテーブル名だけを指定します。 これにより、外部キーの指し示す先がそのテーブルの主キーであると解釈されます。

これらの規則に従い、データベースを定義する SQL 文があれば、データベースのメタデータを作成するのは簡単です。

リレーショナル DAS でのメタデータの扱い

リレーショナル DAS は、データベースのメタデータを使用して SDO モデルの大半を作成します。データベースのメタデータ内にある 各テーブルに対して、SDO 型が定義されます。 プリミティブ型を表すカラム (外部キーとして定義されていないカラム) は、SDO 型のプロパティとして追加されます。

すべてのプリミティブなプロパティは、SDO モデルにおいては 文字列型で表されます。これは、SQL での型が何であっても同じです。 データをデータベースに書き戻す際も、リレーショナル DAS が作成する SQL 文では文字列として扱います。 そして、データベースがそれを適切な型に変換します。

外部キーの扱いかたには二通りの方法があります。 どちらが使用されるかは、コンストラクタの第三引数 (SDO の包含関係について定義するもの) によって決まります。 そのため、これについては以下の SDO の包含関係 の節で改めて説明します。

アプリケーションのルート型の指定

コンストラクタの二番目の引数に指定するのが、アプリケーションのルート型です。 各データグラフの真のルートとなるのは特別なルート型のオブジェクトで、 すべてのアプリケーションデータオブジェクトはその下のどこかに位置します。 SDO モデルのさまざまなアプリケーション型のなかで、 どれかひとつの型がデータグラフのルート直下にある必要があります。 データベースのメタデータ内にテーブルがひとつしかない場合は、 アプリケーションのルート型は推定できます。そのため、この引数は省略可能です。

SDO 包含関係の指定

コンストラクタの三番目の引数で、モデルの型をどのように連結して グラフを構成するかを定義します。複数の型によってグラフが構成される場合に、 その親子関係を指定します。この関係は、 データ内の外部キーでサポートされている必要があります。 これについては後ほど説明します。

メタデータは、ひとつあるいは複数の連想配列を含む配列となります。 個々の連想配列が親と子を表します。以下に company (会社) と department (部署)、そして department (部署) と employee (従業員) の親子関係の例を示します。 これらのそれぞれが SDO のプロパティとなり、 SDO モデルにおける「複数の値をとる包含関係」を定義するものになります。

<?php
$department_containment 
= array( 'parent' => 'company''child' => 'department');
$employee_containment = array( 'parent' => 'department''child' => 'employee');

$SDO_containment_metadata = array($department_containment$employee_containment);           
?>

データベースのメタデータ内にある外部キーは、 複数の値を持つ包含関係のプロパティか 単一の値を持つ包含関係でないプロパティのいずれかと解釈されます。どちらになるかは、 対応する SDO の包含関係がメタデータ内で定義されているかどうかによって決まります。 この例では、department から company への外部キー (department テーブルのカラム co_id) および employee から department への外部キー (employee テーブルのカラム dept_id) が SDO の包含関係と解釈されます。 SDO の包含関係メタデータで示されているそれぞれの関連については、 対応するデータベースメタデータで外部キーが存在しなければなりません。 外部キー列の値は、データオブジェクト内には現れません。その代わりに、 親から子に対する包含関係として表されます。つまり、例えばデータベースの department テーブルにあるカラム co_id は、department 型のプロパティにはなりません。その代わりに、 company 型のほうに department という名前の関係ができます。 ここで、外部キーと親子関係は向きが逆であることに注意しましょう。 外部キーは、department から company に対して指定しますが、 親子関係は company から department に向けて指定します。

この例の三番目の外部キーである employee_of_the_month は、異なる方法で処理されます。これは、SDO の包含関係メタデータとはならず、 もうひとつの方法で解釈されます。company オブジェクト上での 単一の値をとる包含関係でない参照となり、employee 型の SDO データオブジェクトへの参照をそこに代入します。 これは、company 型が持つプロパティとなります。 SDO データグラフ内でこのプロパティに値を代入するには、 employee オブジェクトを含むグラフを取得し、そこに値を代入します。 この方法については、後の例で説明します。