3.1. DAL

DALクラスのインスタンス生成よって、データベースへの接続が可能になります。この他に、テーブル定義・ トランザクション制御・テーブルデータのエクスポート・インポート・SQL文の実行などの機能をメソッドで提供しています。

参考: Dependencies依存関係

DALクラス — データベースに関するクラス

コンストラクタ

データベース接続

define_table()

テーブル定義

commit()rollback()

トランザクション制御

executesql()

直接SQL文を実行

export_to_csv_file()

全テーブルのCSVエクスポート

import_from_csv_file()

複数テーブルのCSVインポート

tables()

テーブル一覧

smart_query()

スマートクエリ

3.1.1. インスタンス化

DALインスタンスの生成は、DALクラスのコンストラクタを使用します。またDALインスタンス名は、デフォルトでは db で設定されています [1]

【 DALインスタンスの生成とアクセス 】

  • 生成・・・・・・ コンストラクタ を使用します。
  • アクセス・・・デフォルトのインスタンス名は db です。
class dal.DAL → DALインスタンス

コンストラクタはデータベースへの接続処理をします。

>>> db = DAL('sqlite://storage.db')
Parameters:
  • uri – 接続文字列
  • pool_size – 接続プール
  • db_codec – データベースのエンコード文字列
  • check_reserved – 予約語チェック
  • migrate – マイグレーション
  • fake_migrate – テーブル定義の再構築
  • migrate_enabled – マイグレーションが可能かどうかの設定
  • fake_migrate_all – 全テーブルで定義の再構築
  • attempts – 接続失敗時の再試行数
  • bigint_idbig-id , big-reference の使用
  • lazy_tables – テーブル定義の遅延実行
  • do_connect – データベースへの接続をするかどうか
Returns:

DALインスタンス

uri

接続文字列については 接続文字列 を参照ください。デフォルト値は ‘sqlite://dummy.db’ です。

複数のデータベースへの接続試行

接続文字列にリスト形式で複数の接続先を記述すると、コンストラクタは順番に接続を試みます。 これは負荷分散目的でデータベースの複製がある場合に利用可能です。

>>> db = DAL(['接続文字列1', '接続文字列2', '接続文字列3', ])

接続文字列1、接続文字列2、接続文字列3 と順番に接続を試していきます。

pool_size

データベース接続でのコネクション数を設定します。デフォルト値は0です。0場合は接続プールは使用しません。

GAE及びSQLiteではこの設定は無視されます。

参考: Connection Pooling接続プール

db_codec
データベースのエンコディングの設定です。デフォルトはUTF-8です。
check_reserved

データベースの予約語が使われているか、チェックを行うかどうかの設定です。デフォルト値はNoneです。

詳細は参考サイトを参照ください。

参考: Reserved Keywords予約されたキーワード

migrate

マイグレーションの設定をします。マイグレーションとはモデル(テーブル)定義が変更になった場合、 自動でデータベース上のテーブルも変更する動作のことです。

デフォルト値はTrueです。モデル定義が変更になった場合に、データベース上のテーブルも変更します。

データが格納されたテーブルのマイグレーションをどうするかなど、考慮すべき点はたくさんあります。詳細は参考サイトを参照ください。

参考: Migrationsマイグレーション

migrate_enabled

接続時に全てのマイグレーションを有効・無効に指定できます。

デフォルトは True です。 False を指定した場合、全てのマイグレーションが無効になります。 複数のアプリケーションがデータベースを共有する場合、一つを除いてマイグレーションを無効にすることが推奨されているので、そのような状況下で使用します。

fake_migrate

マイグレーションの失敗で、モデル定義とデータベーステーブルが不整合になったのを再構築します。

dal.DAL.define_table() メソッドのパラメータとの違いは、define_table はテーブル単位ですが、こちらは全テーブルのマイグレーション問題の 修復をを試みます。しかしこのパラメータの機能では、失敗した場合の原因の究明は難しいです。

デフォルト値はFalseです。再構築する場合はTrueにし、migrateをFalseにします。 再構築完了したらFalseに戻します。詳細は参考サイトを参照ください。

参考: Fixing Broken Migrations壊れたマイグレーションの修復

attempts

接続失敗時の再試行数の設定です。デフォルトは5です。

参考: Connection Failures接続の失敗

bigint_id
id 及び reference フィールドタイプをそれぞれ big-idbig-reference にする場合、Trueで指定します。 デフォルトは False です。
lazy_tables
テーブル定義 define_table() の実行を遅延させます。 モデルで定義したテーブル中で不使用のものがある場合に、このパラメータを指定すると実行速度が上がります。 デフォルトはFalseです。
do_connect

データベースの接続を実際にするかどうかを設定します。デフォルト値はTrueです。 もしFalseを指定した場合、データベースには接続されません。 その場合はアプリケーションは動作しますが、例えば、次のメソッドを使用することはできません。

select()insert()update()delete()

SQL文を生成するだけの次のメソッドは使用可能です。

_select()_insert()_update()_delete()

3.1.2. メソッド

DAL.define_table(tablename, *fields[, **args]) → Tableインスタンス

テーブルの定義をします。

db.define_table('person',
    Field('name'), format='%(name)s')
tablename
テーブル名を文字列で設定します。
*fields
フィールド定義は複数の設定が可能です。定義ではFieldクラスを使用します。 定義方法は Field を参照ください。
**args

オプションを指定します。複数のオプションを指定可能です。設定可能なオプションは次の通りです。

  • format

    レコードの表示方法を指定します。 formatオプションの動作は formatオプションの動作 で説明します。

    設定は、「文字列フォーマット操作」形式もしくは無名関数(lambda)で指定します。

    参考: Record Representationレコードの表現

  • migrate

    マイグレーションログを保存するファイルの名を指定します(省略可能)。 指定したファイル名はアプリケーションの database フォルダに生成されるファイル名になります。

    デフォルトは True です。Trueだとweb2pyの接続文字列のハッシュ値からファイル名を生成します。 False を指定した場合、定義したテーブルのマイグレーションは行われません。

    この他、詳細は参考サイトを参照ください。

    参考: Migrationsマイグレーション

  • fake_migrate

    マイグレーションの失敗で、モデル定義とデータベーステーブルが不整合になったのを再構築します。

    デフォルト値はFalseです。再構築する場合はTrueにし、migrateをFalseにします。 再構築完了したらFalseに戻します。詳細は参考サイトを参照ください。

    参考: Fixing Broken Migrations壊れたマイグレーションの修復

  • primarykey

    レガシテーブルの利用時に、複数フィールドでキーを設定する場合に使用します。 設定するフィールドをリスト形式で指定します。

    primarykey=['ivtype','ivno']
    

    指定しなくてもリストで指定したフィールドは、NOT NULL をセットします。

    primarykey は今のところ、DB2、MS-SQL、Ingres、Informix のみ指定できます。

    primarykeyの設定では レガシデータベースの利用 も参照ください。

  • common_filter

    コモンフィルタ を設定します。

  • この他、次のオプションも設定可能です。

    singular , plural , trigger_name , sequence_name , polymodel , table_class

戻り値
戻り値はTableインスタンスが返ってきます。しかしこれは定義した時点で db.tablenameに関連付けられるため、捉える必要性はありません。

テーブル設定に関しては レガシデータベースの利用テーブルの継承 も参照ください。

参考: DAL, Table, FieldDAL Table Field(日本語)

DAL.commit()

トランザクション制御のコミット処理を行います。

>>> db.commit()

web2py のモデル・ビュー・コントロール のコードは、web2pyによって制御コードが付加されます。 このため、より細かな制御を望まない限り、コミット・ロールバックを記述する必要はありません。

参考: commit and rollbackコミットとロールバック

DAL.rollback()

トランザクション制御のロールバック処理を行います。

>>> db.rollback()

web2py のモデル・ビュー・コントロール のコードは、web2pyによって制御コードが付加されます。 このため、より細かな制御を望まない限り、コミット・ロールバックを記述する必要はありません。

参考: commit and rollbackコミットとロールバック

DAL.executesql(query[, placeholders, as_dict, fields, colnames]) → 実行結果

SQL文を実行できます。

>>> print db.executesql('select * from person')
[(1, u'Syble Zee'), (2, u'Nathanial Azzano'), (3, u'Loreen Depierre')]
>>> print db.executesql('select * from numbers;')
[(1, 8, 71, 799), (2, 954, 364, 402)]

DALではインデックス作成は複雑になるのでサポートしていません。必要なインデックスはこのコマンドを使用して作成可能です。

>>> db.executesql('CREATE INDEX IF NOT EXISTS myidx ON person (name);')
[]
query
SQL文を設定します。
placeholders

プレースホルダ(Queryの置き換え)変数を指定できます。 プレースホルダの構文はDALでは解析されないため、データベースエンジン・ドライバに依存します。

>>> print db.executesql('select * from person where id=:test', placeholders={'test':1})
[(1, u'Syble Zee')]
as_dict

SQL文の実行結果を出力方法を変更できます。デフォルトはFalseです。Trueにした場合、辞書型で結果を出力します。

>>> print db.executesql('select * from person', as_dict=True)
[{'id': 1, 'name': u'Syble Zee'}, {'id': 2, 'name': u'Nathanial Azzano'}, {'id': 3, 'name': u'Loreen Depierre'}]
>>> print db.executesql('select * from numbers',as_dict=True)
[{'a': 8, 'c': 799, 'b': 71, 'id': 1}, {'a': 954, 'c': 402, 'b': 364, 'id': 2}]
fields

SQL文の実行結果とフィールドをマッチングするために指定します。 指定は Field オブジェクトをリストで指定します。 もし Table オブジェクトで指定した場合、 テーブルに含まれる全てのフィールドを指定したことと同等になります。 このパラメータを指定すると結果は、通常のDALクエリと同様に Rows オブジェクトで返ってきます。

fieldsを指定しない場合

>>> rows= db.executesql('select * from person,dog where person.id==dog.owner_id')
>>> print rows
[(1, u'Syble Zee', 1, 1, u'Guadalupe Dadlani'), (2, u'Nathanial Azzano', 2, 2, u'Sook Liechti'),
(3, u'Loreen Depierre', 3, 3, u'Hong Burnet'), (3, u'Loreen Depierre', 4, 3, u'Melonie Osterloh')]

Fieldオブジェクトで指定した場合

>>> rows= db.executesql('select * from person,dog where person.id==dog.owner_id',
... fields=[db.person.id, db.person.name, db.dog.id, db.dog.owner_id, db.dog.name])
>>> print rows
person.id,person.name,dog.id,dog.owner_id,dog.name
1,Syble Zee,1,1,Guadalupe Dadlani
2,Nathanial Azzano,2,2,Sook Liechti
3,Loreen Depierre,3,3,Hong Burnet
3,Loreen Depierre,4,3,Melonie Osterloh

Tableオブジェクトで指定した場合

>>> rows= db.executesql('select * from person,dog where person.id==dog.owner_id',
... fields=[db.person, db.dog])
colnames

fieldsパラメータの代わりに、テーブル名.フィールド名 の形式で、実行結果とフィールドをマッチングさせます。

>>> rows= db.executesql('select * from person,dog where person.id==dog.owner_id',
... colnames=['person.id', 'person.name', 'dog.id', 'dog.owner_id', 'dog.name'])

colnames は fields と同時に指定することも可能です。この場合、colnamesの指定値はフィールドのラベルになります。

>>> rows= db.executesql('select * from person,dog where person.id==dog.owner_id',
... fields=[db.person, db.dog],
... colnames=['person id', 'name', 'dog id', 'dog owner', 'dog name'])
>>> for row in rows:
...     print row['name'] +' - '+ row['dog name']
...
Syble Zee - Guadalupe Dadlani
Nathanial Azzano - Sook Liechti
Loreen Depierre - Hong Burnet
Loreen Depierre - Melonie Osterloh

なお web2py Book には fieldsとcolnamesを同時に指定する場合、fieldsには Expression オブジェクトを 追加可能という記述がありますが、少なくともSQLiteでは動作しないようです。

戻り値
SQL文の実行結果を返します。

参考: Raw SQL生のSQL

DAL.export_to_csv_file()

アプリケーションの全てのテーブルを、CSV形式でエクスポートします。

Rowsクラスの export_to_csv_file メソッドを内部でコールしています。 パラメータも同一です。詳細は export_to_csv_file() を参照ください。

DAL.import_from_csv_file()

CSVファイルから、アプリケーションの複数テーブルのインポートを行います。。

Tableクラスの import_from_csv_file メソッドを内部でコールしています。 パラメータも同一です。詳細は import_from_csv_file() を参照ください。

DAL.tables() → リスト値

定義されているデータベース一覧を返します。

>>> db.tables
['auth_user', 'auth_group', 'auth_membership', 'auth_permission', 'auth_event',
'auth_cas', 'numbers', 'person', 'dog', 'feed', 'cat', 'inventory', 'mouse']
戻り値
テーブル一覧のリスト値
DAL.smart_query(fields, text) → Setインスタンス

自然言語でクエリを実行する、スマートクエリです。詳細は、 スマートクエリ を参照してください。

3.1.3. 特殊メソッド

DALクラスには、いくつか特殊なメソッドが存在します。今回ここでは DALインスタンスに対してテーブル名を辞書型で指定すると、 Table インスタンスを返す特殊メソッドを紹介します。構文は次のようになります。

DALインスタンス[テーブル名] → Tableインスタンス

このメッソドを利用した例としては、アクセス制御で利用する Auth テーブルを考えることができます。Authテーブルはカスタマイズが可能で、 テーブル名自体も変更できます。例えば、auth_user テーブルの名前を変更する場合は、auth.settings.table_user_name 属性値に 新しい名前を設定します。このテーブルの Tableインスタンスを取得したい場合、次のように直接名前を指定することも可能ですが、 ハードコーディングになってしまいます。

>>> rows = db(db.auth_user).select()
>>> for row in rows:
...     print row.first_name, row.last_name
...
Datatodu Tacemapo
Dumacesa Datomoce

次のように特殊メソッドを使った方法で指定すれば、名前を変更した場合にプログラムソースを変更する必要がなくなります。

>>> rows = db(db[auth.settings.table_user_name]).select()
>>> for row in rows:
...     print row.first_name, row.last_name
...
Datatodu Tacemapo
Dumacesa Datomoce

3.1.4. 属性

DAL._dbname

データベース名を保持する属性です。

>>> print db._dbname
sqlite
DAL._lastsql

最後に実行したSQL文を保持する属性です。これは executesql() メソッドを使った場合も使わない場合も、全て記録されます。

>>> rows = db().select(db.numbers.ALL)
>>> print db._lastsql
SELECT  numbers.id, numbers.a, numbers.b, numbers.c FROM numbers;

参考: Raw SQL生のSQL

DAL._timings

データベースドライバーに渡された、SQL文と実行時間(秒)をタプルで保持しています。

>>> db._timings
[('SELECT  person.id, person.name, person.birthday FROM person WHERE (person.id> 0);', 0.004999876022338867),
("INSERT INTO person(name) VALUES ('test');", 0.003000020980834961)]
DAL._uri

接続文字列を保持する属性です。

>>> print db._uri
sqlite://storage.sqlite

[1]Pythonのinstance型オブジェクトではありませんが、簡単に説明するために インスタンス という言葉を使用しています。