SlideShare a Scribd company logo
New O/R Mapper	

for Common Lisp
株式会社はてな	


id:nitro_idiot

2014/01/23 Lisp Meet Up presented by Shibuya.lisp #13
自己紹介
• 深町英太郎	

• id:nitro_idiot	

• 株式会社はてな勤務	

• Webアプリケーションエンジニア	

• ブログ「八発白中」

blog.8arrow.org
作ったもの
• Clack	


• CL-Project	


• Caveman	


• Shelly	


• ningle	


• Lesque	


• CL-TEST-MORE	


• Quickdocs	


• CL-DBI	


• Integral
See 8arrow.org
O/R Mapper
• O/Rマッパー知ってますか	

• DBのデータをオブジェクトとして扱う	

• ObjectStore知ってますか	

• ↑と同じだけど永続化の概念がある
O/R Mapper
• O/Rマッパー知ってますか	

• Postmodern, CLSQL	

• ObjectStore知ってますか	

• Elephant, AllegroCache
O/R Mapper
• O/Rマッパー知ってますか	

• Postmodern, CLSQL	

• ObjectStore知ってますか	

• Elephant, AllegroCache
例: Postmodern
(defclass country ()!
((name :col-type string :initarg :name!
:reader country-name)!
(inhabitants :col-type integer :initarg :inhabitants!
:accessor country-inhabitants)!
(sovereign :col-type (or db-null string) :initarg :sovereign!
:accessor country-sovereign))!
(:metaclass dao-class)!
(:keys name))
例: Postmodern
(defclass country ()!
((name :col-type string :initarg :name!
:reader country-name)!
(inhabitants :col-type integer :initarg :inhabitants!
:accessor country-inhabitants)!
(sovereign :col-type (or db-null string) :initarg :sovereign!
:accessor country-sovereign))!
(:metaclass dao-class)!
(:keys name))

CREATE TABLE country (!
name TEXT NOT NULL,!
inhabitants INTEGER NOT NULL,!
sovereign TEXT,!
PRIMARY KEY (name))
例: Integral
(defclass country ()!
((name :col-type string :initarg :name!
:primary-key t!
:not-null t!
:reader country-name)!
(inhabitants :col-type integer :initarg :inhabitants!
:not-null t!
:accessor country-inhabitants)!
(sovereign :col-type string :initarg :sovereign!
:accessor country-sovereign))!
(:metaclass <dao-table-class>))

Integralでもほとんど同じ。
:metaclassを指定する
メタクラス?
• クラスのクラス	

• クラス定義時に<dao-table-class>のインス

タンスが作成されてcountryクラスになる	

• 指定しないとstandard-classのクラスになる
メタクラス?
• (Integralでは)
• 自動的に

何に使っているか	


<dao-class> を継承させる	


• スロットのクラスを指定できる	

• 通常はstandard-direct-slot-definition	

• その他、定義・再定義時の処理など
メタクラス?
• まあ、変なクラスを作れるってことです。
例: Postmodern
• 話はPostmodernにもどる
例: Postmodern
• defclass

に (:metaclass dao-class) をつける	


• カラムの型を指定できる	

• PRIMARY

KEYを指定できる	


一見、良さそうに見える
既存のORMの問題
• こんなスキーマを開発初期から定義できる

わけねーだろーが!!

(defclass country ()!
((name :col-type string :initarg :name!
:reader country-name)!
(inhabitants :col-type integer :initarg :inhabitants!
:accessor country-inhabitants)!
(sovereign :col-type (or db-null string) :initarg :sovereign!
:accessor country-sovereign))!
(:metaclass dao-class)!
(:keys name))
既存のORMの問題
• 最初にCREATE TABLE文を流してしまう

と、クラス定義を変更したいときに困る	

• カラム追加したくなったら?	

• カラムのデータ型変えたくなったら?	

• Postmodernではテーブルの再作成しかない
Integral
• New

O/Rマッパー	


• Postmodernの持つ問題の解決
Integral
• クラス定義を変更したらDBスキーマにも

変更を反映する
= マイグレーション
マイグレーション
(defclass user ()!
((name :col-type text!
:initarg :name))!
(:metaclass <dao-table-class>))
マイグレーション
(defclass user ()!
((name :col-type text!
:initarg :name)!
(profile :col-type text!
:initarg :profile))!
(:metaclass <dao-table-class>))
マイグレーション
(defclass user ()!
((name :col-type text!
:initarg :name)!
(profile :col-type text!
:initarg :profile))!
(:metaclass <dao-table-class>))

(migrate-table 'user)!
;-> ALTER TABLE `user` ADD COLUMN `profile` TEXT AFTER `name`;!
;=> NIL
マイグレーション
(defclass user ()!
((id :col-type serial!
:primary-key t)!
(name :col-type (varchar 64)!
:initarg :name)!
(profile :col-type text!
:initarg :profile))!
(:metaclass <dao-table-class>))

(migrate-table 'user)!
;-> ALTER TABLE `user` DROP COLUMN `%oid`;!
;
ALTER TABLE `user` MODIFY COLUMN `name` VARCHAR(64);!
;
ALTER TABLE `user` ADD COLUMN `id` SERIAL NOT NULL PRIMARY
KEY FIRST;!
;=> NIL
オートマイグレーションモード
• *auto-migration-mode*をTにすると発動	

• クラスを再定義するたびにmigrate-table	

• 開発時に超便利
マイグレーションの実装
• 泥臭い	

• 普通にDBスキーマ引いてきてスロットと

比較しているだけ	

• DBの種類を見て、ValidなSQLを吐く	

• ALTER TABLEの実行順序も考慮
オートマイグレーションモードの実装
• initialize-instance

と reinitialize-instance の :after

で *auto-migration-mode* の値を見て T なら
migrate-table 走らせるだけ
Integral	

• クラス定義

→ DBスキーマ の追随の話を

しましたね。	

• 既にあるテーブルと一緒に使うにはどうし

たらいいの???
Integral	

• DBスキーマ

よ

→ クラス定義 の追随もできる
:generate-slots	

!
!

(defclass user () ()!
(:metaclass <dao-table-class>)!
(:generate-slots t))

DBからスキーマ定義を取ってきてスロット
をつっこむ
:generate-slots	

!
!

(defclass user () ()!
(:metaclass <dao-table-class>)!
(:generate-slots t))

DBからスキーマ定義を取ってきてスロット
をつっこむ
(make-instance 'user :name "Eitarow Fukamachi")!
;=> #<USER %oid: <unbound>>
:generate-slots	

!
!

(defclass user () ()!
(:metaclass <dao-table-class>)!
(:generate-slots t))

DBからスキーマ定義を取ってきてスロット
をつっこむ
class User < ActiveRecord::Base!
end
:generate-slots	

!
!

(defclass user () ()!
(:metaclass <dao-table-class>)!
(:generate-slots t))

DBからスキーマ定義を取ってきてスロット
をつっこむ
class User < ActiveRecord::Base!
end

なんか似てますね
:generate-slots	

の実装
• 定義したときはスロットは空	

• 最初にmake-instanceする直前にDBスキーマ

を取ってきてスロットをつっこむ	

• 定義時にやらない理由は、定義時にDB

接続がある保証が無いから
:generate-slots	

の実装
• 既存のクラスにスロットを追加するのは

意外と面倒	

• c2mop:ensure-class-using-class

を使って上書

きする	

• このときスロット名が同じものが既に定

義されてると死ぬのでちゃんとマージする
CRUD
•

Create: (save-dao (make-instance ‘user :name “Eitarow”))	


•

Read: (select-dao ‘user (where (:= :name “Eitarow”)))	


•

Update: (save-dao user-obj)	


•

Delete: (delete-dao user-obj)
CRUD
• update-daoやdelete-daoのとき実行される

SQLはUPDATE文とDELETE文	

• WHERE句が一意である必要がある	

• (でないと関係ない列まで変更する)	

• 通常はPRIMARY

KEYを使う
CRUD
• Integralでは、PRIMARY

KEYの定義が無いと

きは自動で%oidというPRIMARY KEYを付与	

• 後でPRIMARY

KEYが定義されるとマイグ

レーションでDROP COLUMNされるから
別に問題ないよね
暗黙の継承<dao-table>
• select-dao, save-dao, delete-dao

は <dao-table>

のメソッドとして定義されている	

• Postmodernでは定義クラスが単一のクラス

を継承しない (metaclassのみ)	

• テーブルクラスに共通のメソッドを定義で

きない
共通のクラスを継承する利点
• たとえばRailsのScaffoldみたいな機能	

• テーブルクラスからHTMLのformを吐くみ

たいな機能が作れる	

• 他バリデーション機能とか
Postmodern vs Integral
Postmodern

Integral

対応DB

PostgreSQL

MySQL, PostgreSQL,
SQLite3

マイグレー
ション

なし

あり

自動PK

なし

あり

なし

あり

スロット

自動生成
Integral

https://github.com/fukamachi/integral

More Related Content

KEY
Shelly
ODP
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
PDF
Clojureで作る"simple"なDSL
PDF
GraphQL入門
PDF
Clojure REPL: The Good Parts
PDF
Everyday Life with clojure.spec
PDF
Ductモジュール入門
PDF
本番環境で使える実行コード記録機能
Shelly
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
Clojureで作る"simple"なDSL
GraphQL入門
Clojure REPL: The Good Parts
Everyday Life with clojure.spec
Ductモジュール入門
本番環境で使える実行コード記録機能

What's hot (20)

PDF
なぜリアクティブは重要か #ScalaMatsuri
PDF
about Perl5.10
PDF
ECMAScript6による関数型プログラミング
PDF
はてなブックマーク in Scala
PDF
20131208 agile samuraibasecamp
PDF
20140930 anything as_code
PDF
OSSから学ぶSwift実践テクニック
PDF
Why Reactive Matters #ScalaMatsuri
PDF
マニアックなRuby 2.7新機能紹介
PDF
ScalaMatsuri 2016
PDF
Akka stream
PDF
いまどきのPHP
PDF
Lightweight C#
PDF
Miyazaki.js vol.1 スコープの話
PPTX
Yesod勉強会
PDF
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
PDF
あなたのScalaを爆速にする7つの方法(日本語版)
PDF
はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化
PDF
serverless framework + AWS Lambda with Python
なぜリアクティブは重要か #ScalaMatsuri
about Perl5.10
ECMAScript6による関数型プログラミング
はてなブックマーク in Scala
20131208 agile samuraibasecamp
20140930 anything as_code
OSSから学ぶSwift実践テクニック
Why Reactive Matters #ScalaMatsuri
マニアックなRuby 2.7新機能紹介
ScalaMatsuri 2016
Akka stream
いまどきのPHP
Lightweight C#
Miyazaki.js vol.1 スコープの話
Yesod勉強会
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
あなたのScalaを爆速にする7つの方法(日本語版)
はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化
serverless framework + AWS Lambda with Python
Ad

Viewers also liked (20)

PDF
Dexador Rises
KEY
About Clack
PDF
Woo: Writing a fast web server
PDF
Woo: Writing a fast web server @ ELS2015
PDF
Writing a fast HTTP parser
PDF
Clack: glue for web apps
PDF
Mito, a successor of Integral
PDF
Lisp Poetry
PDF
Lispで仕事をするために
ODP
Lisp Meet Up #31, Clake: a GNU make-like build utility in Common Lisp
PDF
SBLint
PDF
Redesigning Common Lisp
PDF
Building GUI App with Electron and Lisp
PDF
すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~
KEY
自分をClojure化する方法
PDF
JavaからClojure、そして夢の世界へ
KEY
第四回関西Emacs「ari.el」
PDF
Clack & Caveman
PDF
Lisperの見る世界
ODP
CL21で色々なデータ構造を実装してみようとした
Dexador Rises
About Clack
Woo: Writing a fast web server
Woo: Writing a fast web server @ ELS2015
Writing a fast HTTP parser
Clack: glue for web apps
Mito, a successor of Integral
Lisp Poetry
Lispで仕事をするために
Lisp Meet Up #31, Clake: a GNU make-like build utility in Common Lisp
SBLint
Redesigning Common Lisp
Building GUI App with Electron and Lisp
すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~
自分をClojure化する方法
JavaからClojure、そして夢の世界へ
第四回関西Emacs「ari.el」
Clack & Caveman
Lisperの見る世界
CL21で色々なデータ構造を実装してみようとした
Ad

Similar to Integral - New O/R Mapper for Common Lisp (20)

PDF
Scalaプログラミング・マニアックス
PDF
Object-Funcational Analysis and design
PDF
オブジェクト指向開発におけるObject-Functional Programming
PDF
ng-japan 2015 TypeScript+AngularJS 1.3
PDF
Functional JavaScript with Lo-Dash.js
PDF
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
PDF
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
PDF
WordBench Kobe jQueryどうでしょう
PDF
Ruby Sapporo Night Vol4
PDF
AWS SDK for Smalltalk
PDF
Shibuya.lisp #28: 仮題: R について
PDF
Scalaで萌える関数型プログラミング[完全版]
KEY
Aizu lt tokyo_luxion
PDF
クライアントサイドjavascript簡単紹介
PDF
SPARQLから入門するLinked Open Data(LOD)ハンズオン 第2回
PDF
Haikara
PDF
⑲jQueryをおぼえよう!その5
PDF
⑯jQueryをおぼえよう!その2
PDF
実務者のためのかんたんScalaz
PDF
named_scope more detail - WebCareer
Scalaプログラミング・マニアックス
Object-Funcational Analysis and design
オブジェクト指向開発におけるObject-Functional Programming
ng-japan 2015 TypeScript+AngularJS 1.3
Functional JavaScript with Lo-Dash.js
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
WordBench Kobe jQueryどうでしょう
Ruby Sapporo Night Vol4
AWS SDK for Smalltalk
Shibuya.lisp #28: 仮題: R について
Scalaで萌える関数型プログラミング[完全版]
Aizu lt tokyo_luxion
クライアントサイドjavascript簡単紹介
SPARQLから入門するLinked Open Data(LOD)ハンズオン 第2回
Haikara
⑲jQueryをおぼえよう!その5
⑯jQueryをおぼえよう!その2
実務者のためのかんたんScalaz
named_scope more detail - WebCareer

Integral - New O/R Mapper for Common Lisp