Mito, a successor of Integral

Post on 26-Jan-2017

752 views 0 download

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

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

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.

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 “e.arrows@gmail.com” :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 “e.arrows@gmail.com” :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