Mito, a successor of Integral
-
Upload
fukamachi -
Category
Technology
-
view
752 -
download
0
Transcript of Mito, a successor of Integral
MITO, A SUCCESSOR OF INTEGRAL
LISP MEETUP #43 Aug 30, 2016
I’m Eitaro Fukamachi @nitro_idiot fukamachi
Do you use RDBMS?
Do you know O/R Mapper?
RDBMS
Record
Record
Record
TableTable
Table
RDBMS
Record
Record
Record
TableTable
Table
CLOS class CLOS class
CLOS class
RDBMS
Record
Record
Record
TableTable
Table
CLOS class CLOS class
CLOS class
make-instance
RDBMS
Record
Record
Record
TableTable
Table
CLOS class CLOS class
CLOS class
CLOS Object
CLOS Object
CLOS Object
make-instance
CLOS class CLOS class
CLOS class
CLOS Object
CLOS Object
CLOS Object
make-instance
CLOS class CLOS class
CLOS class
CLOS Object
CLOS Object
CLOS Object
make-instance
▸ Abstracts RDBMS including SQL
▸ Maps RDB tables to CLOS classes
▸ Maps RDB records to CLOS objects
▸ Can add methods
▸ Accelerates development
Do you know O/R Mapper?
ORM Examples
▸ CLSQL
▸ Postmodern
▸ Integral
Do you know O/R Mapper?
ORM Examples
▸ CLSQL
▸ Postmodern
▸ Integral
A talk about “Integral”
2 years ago
Do you know O/R Mapper?
ORM Examples
▸ CLSQL
▸ Postmodern
▸ Integral
▸ Crane
A talk about “Integral”
2 years ago
Do you know O/R Mapper?
ORM Examples
▸ CLSQL
▸ Postmodern
▸ Integral (Not recommended)
▸ Crane
▸ Mito
A talk about “Integral”
2 years ago
NEW!
What’s new in Mito?
What’s new in Mito?
Mito, a successor of Integral▸ Supports PostgreSQL, as well as MySQL & SQLite3
▸ Implicit columns (auto-pk & record-timestamps)
▸ Reference between DB table classes
▸ Eager loading
▸ Inheritance of DB table classes
▸ Migrations
▸ Schema versioning
Implicit columns, auto-pk & record-timestamps
(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
CREATE TABLE user ( id BIGSERIAL NOT NULL PRIMARY KEY, name VARCHAR(64) NOT NULL, email VARCHAR(128), created_at TIME, updated_at TIME )
(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
CREATE TABLE user ( id BIGSERIAL NOT NULL PRIMARY KEY, name VARCHAR(64) NOT NULL, email VARCHAR(128), created_at TIME, updated_at TIME )
(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
CREATE TABLE user ( id BIGSERIAL NOT NULL PRIMARY KEY, name VARCHAR(64) NOT NULL, email VARCHAR(128), created_at TIME, updated_at TIME )
(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
CREATE TABLE user ( id BIGSERIAL NOT NULL PRIMARY KEY, name VARCHAR(64) NOT NULL, email VARCHAR(128), created_at TIME, updated_at TIME )
(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
CREATE TABLE user ( id BIGSERIAL NOT NULL PRIMARY KEY, name VARCHAR(64) NOT NULL, email VARCHAR(128), created_at TIME, updated_at TIME )
(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
auto-pk
record-timestamps
Reference between DB table classes
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user-id :col-type (:bigint () :unsigned) :initarg :user-id :accessor tweet-user-id)) (:metaclass mito:dao-table-class))
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user-id :col-type (:bigint () :unsigned) :initarg :user-id :accessor tweet-user-id)) (:metaclass mito:dao-table-class))
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defun tweet-user (tweet) (mito:find-dao ‘user :id (tweet-user-id tweet)))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user-id :col-type (:bigint () :unsigned) :initarg :user-id :accessor tweet-user-id)) (:metaclass mito:dao-table-class))
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defun tweet-user (tweet) (mito:find-dao ‘user :id (tweet-user-id tweet)))
These kind of accessors are quite common.
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user :col-type user :initarg :user :accessor tweet-user)) (:metaclass mito:dao-table-class))
It may cause a performance issue: N+1 query.
Eager loading helps.
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user :col-type user :initarg :user :accessor tweet-user)) (:metaclass mito:dao-table-class))
;; Tweets contain “Japan” (select-dao 'tweet (where (:like :status “%Japan%")))
;; Getting names of tweeted users. (mapcar (lambda (tweet) (user-name (tweet-user tweet))) *)
BAD EXAMPLE
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user :col-type user :initarg :user :accessor tweet-user)) (:metaclass mito:dao-table-class))
;; Tweets contain “Japan” (select-dao 'tweet (where (:like :status “%Japan%")))
;; Getting names of tweeted users. (mapcar (lambda (tweet) (user-name (tweet-user tweet))) *)
SQL execution for each records. (N times)
BAD EXAMPLE
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user :col-type user :initarg :user :accessor tweet-user)) (:metaclass mito:dao-table-class))
;; Tweets contain “Japan” (select-dao 'tweet (includes 'user) (where (:like :status “%Japan%")))
;; No additional SQLs will be executed. (tweet-user (first *))
GOOD EXAMPLE
Reference between DB table classes
(defclass user () … (:metaclass mito:dao-table-class))
(defclass tweet () ((status :col-type :text :initarg :status :accessor tweet-status) (user :col-type user :initarg :user :accessor tweet-user)) (:metaclass mito:dao-table-class))
;; Tweets contain “Japan” (select-dao 'tweet (includes 'user) (where (:like :status “%Japan%")))
;; No additional SQLs will be executed. (tweet-user (first *))
Throw 1 query to retrieve users beforehand.
GOOD EXAMPLE
Inheritance of DB table classes
Sometimes similar DB tables are needed.
Photo by Andrey Shipilov
Inheritance of DB table classes
Ex) SQL Antipatterns: Logical Deletion
slideshare.net/t_wada/ronsakucasual
slideshare.net/SoudaiSone/postgre-sql-54919575
PostgreSQL Antipatterns
Inheritance of DB table classes
Ex) SQL Antipatterns: Logical Deletion(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
(defclass deleted-user (user) ((deleted-at :col-type :datetime :initarg :deleted-at :initform (local-time:now) :accessor user-deleted-at)) (:metaclass mito:dao-table-class))
Inheritance of DB table classes
Ex) SQL Antipatterns: Logical Deletion(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
(defclass deleted-user (user) ((deleted-at :col-type :datetime :initarg :deleted-at :initform (local-time:now) :accessor user-deleted-at)) (:metaclass mito:dao-table-class))
CREATE TABLE deleted_user ( id BIGSERIAL NOT NULL PRIMARY KEY, name VARCHAR(64) NOT NULL, email VARCHAR(128), deleted_at TIME NOT NULL, created_at TIME, updated_at TIME )
Inheritance of DB table classes
Ex) SQL Antipatterns: Logical Deletion(defclass user () ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
(defclass deleted-user (user) ((deleted-at :col-type :datetime :initarg :deleted-at :initform (local-time:now) :accessor user-deleted-at)) (:metaclass mito:dao-table-class))
CREATE TABLE deleted_user ( id BIGSERIAL NOT NULL PRIMARY KEY, name VARCHAR(64) NOT NULL, email VARCHAR(128), deleted_at TIME NOT NULL, created_at TIME, updated_at TIME )
Inheritance of DB table classes
Ex) SQL Antipatterns: Logical Deletion
(defmethod mito:delete-dao :before ((user user)) (mito:create-dao ‘deleted-user :id (object-id user) :name (user-name user) :email (user-email user) :created-at (object-created-at user) :updated-at (object-updated-at user)))
Copy “user” records to “deleted_user” before deleting.
Mixin DB table injection
Photo by Steve Snodgrass
Inheritance of DB table classes - Mixin
Mixin
▸ Injects columns and methods
▸ record-timestamps is an actual example
▸ Adds created_at & updated_at
Inheritance of DB table classes - Mixin
Ex) mito-auth
▸ Managing user passwords is dull
▸ Stores hashed passwords
▸ Authenticates
github.com/fukamachi/mito-auth
Inheritance of DB table classes - Mixin
Ex) mito-auth(defclass user (has-secure-password) ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
github.com/fukamachi/mito-auth
Inheritance of DB table classes - Mixin
Ex) mito-auth(defclass user (has-secure-password) ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
(mito:create-dao ‘user :name “fukamachi” :email “[email protected]” :password “c0mmon-l1sp”)
github.com/fukamachi/mito-auth
Inheritance of DB table classes - Mixin
Ex) mito-auth(defclass user (has-secure-password) ((name :col-type (:varchar 64) :initarg :name :accessor user-name) (email :col-type (or (:varchar 128) :null) :initarg :email :accessor user-email)) (:metaclass mito:dao-table-class))
(mito:create-dao ‘user :name “fukamachi” :email “[email protected]” :password “c0mmon-l1sp”)
Stores a hashed password and salt, not a plain text.
github.com/fukamachi/mito-auth
What wasn’t mentioned▸ Migrations
▸ Schema versioning
▸ Inflation/deflation
▸ See https://github.com/fukamachi/mito
Thanks.
EITARO FUKAMACHI 8arrow.org @nitro_idiot fukamachi
Thanks.
See Also
▸ https://github.com/fukamachi/mito
▸ https://github.com/fukamachi/mito-auth
▸ https://github.com/fukamachi/mito-attachment