Perl入門ゼミ

テキスト処理、Linuxサーバー管理、Web開発ならPerl
  1. Perl
  2. モジュール
  3. データベース
  4. DBIx::Custom
  5. here

DBIx::Customの「テーブル」と「列」の情報を調べるメソッド

DBIx::Customの「テーブル」と「列」の情報を調べるメソッドを紹介します。

すべてのテーブルの情報を順番に調べる each_table

すべてのテーブルの情報を順番に調べるにはeach_tableメソッドを使用します。

$dbi->each_table(
  sub {
    my ($dbi, $table, $table_info) = @_;
    
    my $table_name = $table_info->{TABLE_NAME};
  }
);

データベースにあるすべてのテーブルの情報を順番にたどります。引数にはテーブルごとに実テーブルされるコールバック関数を指定します。コールバック関数は次の3つの引数を受け取ります。

  1. DBIx::Customオブジェクト
  2. テーブル名
  3. テーブルの情報

each_tableの高速化

each_tableメソッドは遅いです。特に大量のシステムテーブルがデータベースに存在する場合は、かなり遅いです。

もしuser_table_infoが設定されている場合は、each_tableはテーブルの情報としてこれを利用します。次のようにしてeach_tableを高速化することができます。

my $table_infos = $dbi->get_table_info(exclude => qr/^system_/);
$dbi->user_table_info($table_info);
$dbi->each_table(sub { ... });

テーブルの情報を取得する get_table_info

テーブルの情報を取得するにはget_table_infoメソッドを使用します。

my $table_infos = $dbi->get_table_info(exclude => qr/^system_/);

excludeオプションで、除外するテーブル名を正規表現で指定することができます。

データベースのテーブルの情報を設定する - user_table_info

データベースのテーブルの情報を取得するには通常はeach_tableメソッドを利用しますが、システムテーブルを大量に保持しているデータベースの場合は、アクセスするたびにテーブルの情報の取得を行うと非常に低速になります。

user_table_infoメソッド使用すると、テーブル情報を設定しておいて、each_tableがそのテーブル情報を利用できるようになります。

$dbi->user_table_info($user_table_info)

each_tableメソッドは非常に速くなります。

設定する情報のデータ構造は以下のようになっています。

[
  {table => 'book', info => {...}},
  {table => 'author', info => {...}}
]

通常はget_table_infoであらかじめ取得しておいた情報をuser_table_infoに設定します。

my $user_table_info = $dbi->get_table_info(exclude => qr/^system/);
$dbi->user_table_info($user_table_info);

列の情報を取得する - get_column_info

列の情報を取得するにはget_column_infoメソッドを使用します。

my $column_infos = $dbi->get_column_info(exclude_table => qr/^system_/);

exclude_tableオプションで、除外するテーブル名を正規表現で指定することができます。

すべての列の情報を順番に調べる - each_column

すべての列の情報を順番に調べるにはeach_columnメソッドを使用します。

$dbi->each_column(
  sub {
    my ($dbi, $table, $column, $column_info) = @_;
    
    my $type = $column_info->{TYPE_NAME};
    
    if ($type eq 'DATE') {
      # ...
    }
  }
);

データベースにあるすべての列の情報を順番にたどります。引数には列ごとに実行されるコールバック関数を指定します。コールバック関数は次の4つの引数を受け取ります。

  1. DBIx::Customオブジェクト
  2. テーブル名
  3. 列名
  4. 列の情報

each_columnの高速化

each_columnメソッドは遅いです。特に大量のシステム列がデータベースに存在する場合は、かなり遅いです。

もしuser_column_infoが設定されている場合は、each_columnは列の情報としてこれを利用します。次のようにしてeach_columnを高速化することができます。

my $column_infos = $dbi->get_column_info(exclude_table => qr/^system_/);
$dbi->user_column_info($column_info);
$dbi->each_column(sub { ... });

この方法で、each_columnを内部で利用している、setup_modelとtype_ruleも高速化されます。

データベースの列の情報を設定する - user_column_info

データベースの列の情報を取得するには通常はeach_columnメソッドを利用しますが、システムテーブルを大量に保持しているデータベースの場合は、アクセスするたびに列の情報を取得すると非常に低速になります。

user_column_infoメソッドを使用すると、列情報を設定でき、each_columnがこの列情報を利用できるようになります。

$dbi->user_column_info($user_column_info)

each_columnメソッドは非常に高速になりますし、type_ruleやsetup_modelといったeach_columnを内部で利用しているメソッドも速くなります。

設定する情報のデータ構造は以下のようになっています。

[
  {table => 'book', column => 'title', info => {...}},
  {table => 'author', column => 'name', info => {...}}
]

通常はget_column_infoであらかじめ取得しておいた情報をuser_column_infoに設定します。

my $user_column_info = $dbi->get_column_info(exclude_table => qr/^system/);
$dbi->user_column_info($user_column_info);

テーブルを指定してすべての列のタイプ名を表示する show_typename

テーブルを指定してすべての列のタイプ名を表示するにはshow_typenameメソッドを使用します。

$dbi->show_typename($table);

一行目にはテーブル名、2行目以降は列名とタイプ名が表示されます。

book
title: varchar
issue_date: date

このタイプ名はtype_ruleのinto1とinto2で利用することができます。

指定したテーブルのすべての列のデータタイプを表示する - show_datatype

指定したテーブルのすべての列のデータタイプを表示するにはshow_datatypeメソッドを使用します。

$dbi->show_datatype($table);

一行目はテーブル名、2行目以降は列名とデータタイプが表示されます。

book
title: 5
issue_date: 91

このデータタイプはtype_ruleのfrom1とfrom2で利用することができます。

タイプ名の一覧の取得 available_typename

データベースで利用できるタイプ名の一覧を取得するにはavailable_typenameメソッドを使用します。

print $dbi->available_typename;

タイプ名は、データベースのテーブル定義の時に指定する型とだいたい一致しますが、完全に一致するわけではないので注意してください。

正しいタイプ名を知るにはshow_typenameメソッドを使用してください。

データタイプの一覧の取得 available_datatype

データベースで利用できるデータタイプの一覧を取得するにはavailable_datatypeメソッドを使用します。

print $dbi->available_datatype;

このメソッドで列挙されるデータタイプは以下のようなロジックで取得されるものです。

for my $i (-1000 .. 1000) {
  $dbh->type_info($i);
  my $data_type = $type_info->{DATA_TYPE};
}

ステートメントハンドルのTYPE属性で取得できる値と似ていますが、まったく一致するわけではいようですので注意してください。またSQLiteでは、何も列挙されません。

$sth->{TYPE}

正しいデータタイプを知るにはshow_datatypeメソッドを利用してください。

PostgreSQLで利用可能なデータタイプ

DBIで取得できるPostgreSQLで利用可能なDataTypeです。

Data Type (Type name)

-3 (bytea)

0 (unknown)

1 (bpchar)

2 (numeric)

3 (numeric)

4 (int4)

5 (int2)

6 (float4)

7 (float8)

8 (int8)

9 (date) # これは間違っているのかも

10 (tinterval)

11 (timestamp)

12 (text)

16 (bool)

50 (array)

91 (date) # dateはこれが正しいとおもいます。

92 (time)

93 (timestamp)

94 (timetz)

95 (timestamptz)

Microsoft SQL Server 2008 R2で利用可能なデータタイプ

DBIで取得できるMicrosoft SQL Server 2008 R2が返すデータタイプの一覧です。available_datatypeの値。DBD::ODBC経由でアクセスしたときのものです。

Data Type (Type name)
-150 (sql_variant)
-11 (uniqueidentifier)
-10 (ntext)
-9 (nvarchar)
-8 (nchar)
-7 (bit)
-6 (tinyint)
-5 (bigint)
-4 (image)
-3 (varbinary)
-2 (binary)
-1 (text)
-150 (sql_variant)
1 (char)
2 (numeric)
3 (decimal)
4 (int)
5 (smallint)
6 (float)
7 (real)
12 (varchar)
93 (datetime)

date型が見当たりませんが、SQL ServerではDate型はなんと、-9(nvarchar)で返ってくるようです。date型の場合はSQLサーバーの場合は、自動判定ができないようです。

検索するテーブルから特定のテーブルを除外する - exclude_table

DBIx::Customにはデータベースのテーブルを検索するメソッドがあります。特定のテーブルを検索対象から除外したい場合はexclude_tableを利用します。

$dbi->exclude_table(qr/pg_/);

値には正規表現のリファレンスを指定します。

each_column, each_table, type_rule, setup_modelという四つのメソッドは、データベースのテーブル情報を取得しにいきますが、exclude_tableで指定された正規表現にマッチしたテーブルを検索対象から除外します。

Microsoft SQL ServerやOracleは内部に大量のシステムテーブルを保持しているので、うまく設定すればパフォーマンスがよくなります。

  • Perlとはテキスト処理の記述性とパフォーマンスに優れ、正規表現が言語に組み込まれているプログラミング言語です。
  • Linuxサーバーでのフィルタリングプログラム、複数行の文字列を処理、ファイル内容の検索・置換などが得意
  • Perlはgitopensslなど広く普及したUnix/Linuxミドルウェアの補助ツールとして採用実績あり。後方互換性とポータビリティの高さがひとつの理由と推測。
  • 大量のテキストを扱うWeb開発も得意。ロングテールSEOを意識したWebサイト、アドテクやソーシャルゲームでの50ms以内のJSONの生成など。