SlideShare a Scribd company logo
Lobos      Introduction
Presentation given to the Bonjure group on 2011/01/21.
Outline
●   Overview & basic concepts
●   Past: history and development
    highlights
●   Present: examples, project structure
    and architecture
●   Future: migrations and declarative
    schema manipulation
Overview
     Clojure code                      SQL Statement(s)*

(create                           CREATE TABLE "users" (
 (table :users                      "name" VARCHAR(100),
   (integer :id :auto-inc           "id" SERIAL,
                :primary-key)       CONSTRAINT "min_length"
   (varchar :name 100 :unique)        CHECK (length("name") > 1),
   (check :min_length               CONSTRAINT "users_unique_name"
          (> :length/name 1))))       UNIQUE ("name"),
                                    CONSTRAINT "users_primary_key_id"
                                      PRIMARY KEY ("id"))



      Note that the syntax is partially inspired by
           ActiveRecord::Migration
        *This example use the PostgreSQL backend.
Basic Concepts
●   Abstract Schema Definition: Used
    internally to represent a database
    schema.
●   Action: Functions executing
    imperative SQL statements.
●   AST: Intermediate database-agnostic
    representation of SQL statements.
Past
History
●   Lobos is based on the original
    ClojureQL project which was based
    on SchemeQL.
●   It's a complete rewrite of the DDL part.
●   Lobos is less than a month old and a
    one-man effort for now.
Development Highlights
●   Uses most Clojure features and best
    practices.
●   Namespace structure makes the
    project very modular.
●   Bugs in Clojure code can be hard to
    diagnose, beware of laziness!
Present
Examples
(use 'lobos.connectivity)


(def pg
  {:classname      "org.postgresql.Driver"
   :subprotocol    "postgresql"
   :user           "test"
   :password       "test123"
   :subname        "//localhost:5432/test"})


(open-global pg)
(close-global)                   ||       (open-global :pg pg)
                                          (close-global :pg)



You can specify a connection map (or global
connection name) as the first argument of an
action or use the global default connection.
Examples
All elements are constructed using functions or macros that yield
Clojure data structures and thus are composable. Here we define
some helpers:
(use 'lobos.schema)


(defn surrogate-key [table]
  (integer table :id :auto-inc :primary-key))


(defmacro tabl [name & elements]
  `(-> (table ~name (surrogate-key))
       ~@elements))


(defn refer-to [table ptable]
  (let [cname (-> (->> ptable name butlast (apply str))
                  (str "_id")
                  keyword)]
    (integer table cname [:refer ptable :id
                                 :on-delete :set-null])))
Examples
With the previously defined custom functions and macros we can
define a more complex schema with less code...

(use 'lobos.core)


(defschema sample-schema :lobos

  (tabl :users
    (varchar :name 100 :unique)
    (check :name (> :length/name 1)))

  (tabl :posts
    (varchar :title 200 :unique)
    (text :content)
    (refer-to :users))

  (tabl :comments
    (text :content)
    (refer-to :users)
    (refer-to :posts)))
Examples
Schemas created with defschema are functions returning an
abstract schema!
(create-schema sample-schema)


(set-default-schema sample-schema)


(drop (table :posts) :cascade)


(drop-schema sample-schema :cascade)



The cascade behavior works even in SQL Server which doesn't
support that feature!
Dropping a schema created with defschema makes the defined
function return nil, so just pretend we didn't evaled that line!
   Warning: all uses of exclamation points in this slide are completely superfluous!
Examples
(alter :add (table :users (text :bio)))


(alter :add (table :users
              (text :location)
              (text :occupation)))


(alter :add (table :posts
              (check :content_limit
                     (< :length/content 1337))))


(alter :modify (table :users
                 (column :location
                         [:default "somewhere"])))


(alter :drop (table :users (column :occupation)))


(alter :rename (table :users
                 (column :location :to :origin)))
Any questions yet?

Do we need a break?
Project Structure
●   Frontend
       lobos.core
       lobos.schema
       lobos.connectivity
●   Backend
       lobos.compiler
       lobos.ast
       lobos.backends.*
●   Analyzer
       lobos.metadata
       lobos.analyzer
Project Structure
connectivity      core
                              *
     analyzer   schema       utils



     metadata     ast      compiler




                backends
Architecture
● Actions yield Abstract Schema
  Definitions
● Schema protocols build a AST(s) from

  ASDs
● The compiler (compile multi-method)

  generates the appropriate SQL
  statements from an AST.
● The analyzer constructs an abstract

  schema ASD from a real schema.
Architecture
(defrecord Table [name columns constraints options]
  Alterable Creatable Dropable

 (build-alter-statement [this action db-spec]
   (let [elements (map #(build-definition (second %) db-spec)
                       (concat columns constraints))]
     (for [element elements]
       (AlterTableStatement.
        db-spec
        name
        action
        element))))

 (build-create-statement [this db-spec]
   (CreateTableStatement.
    db-spec
    name
    (map #(build-definition (second %) db-spec)
         (concat columns constraints))))

 (build-drop-statement [this behavior db-spec]
   (DropStatement. db-spec :table name behavior)))
Architecture
(def backends-hierarchy
  (atom (-> (make-hierarchy)
            (derive :h2 ::standard)
            (derive :mysql ::standard)
            (derive :postgresql ::standard)
            (derive :sqlite ::standard)
            (derive :sqlserver ::standard))))

(defmulti compile
  (fn [o]
    [(-> o :db-spec :subprotocol (or ::standard) keyword)
     (type o)])
  :hierarchy backends-hierarchy)

...

(defmethod compile [::standard AutoIncClause] [_]
  "GENERATED ALWAYS AS IDENTITY")

...
(defmethod compile [:mysql AutoIncClause] [_]
  "AUTO_INCREMENT")
Future
Migrations
Objectives:
 ●   Could be written manually, like in
     ActiveRecord::Migration
 ●   Could be automatically generated
     when actions are entered at the
     REPL
 ●   Also automatically generated when
     declaratively changing a schema
     definition (see next slide)
Declarative Schema Manipulation
Say we are working on a database built from the following
schema:
(defschema sample-schema :lobos

  (table :users
    (varchar :name 100 :unique)
    (check :name (> :length/name 1)))
...


Instead of imperatively issuing alter statements, wouldn't it
be great to just change it?
(defschema sample-schema :lobos

  (table :users
    (varchar :name 100 :unique)
    (text :bio)
    (check :name (> :length/name 1)))
...
I need your help!
 Visit the project's
    github page:
    https://github.com/budu/lobos


   Any questions
    suggestions,
comments or insults?
Links
Website:
  http://budu.github.com/lobos/
Code Repository:
  https://github.com/budu/lobos
Issue Tracker:
  https://github.com/budu/lobos/issues
Wiki:
  https://github.com/budu/lobos/wiki
Acknowledgments
Thanks (in alphabetical order) to:
 ● James Reeves (for Hiccup)
 ● Lau B. Jensen (for the old and new ClojureQLs)


 ● Meikel Brandmeyer (for working with me on the old ClojureQL)


 ● Michael Fogus (for Marginalia and "The Joy of Clojure" book)


 ● Phil Hagelberg (for Leiningen)


 ● Rich Hickey (for Clojure)


 ● Stephen C. Gilardi (for clojure.contrib.sql)




Also thanks to all Clojure contributors and to
its fantastic community!
The End!

More Related Content

What's hot

Perl Stored Procedures for MySQL (2009)
Perl Stored Procedures for MySQL (2009)Perl Stored Procedures for MySQL (2009)
Perl Stored Procedures for MySQL (2009)
Antony T Curtis
 
External Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLExternal Language Stored Procedures for MySQL
External Language Stored Procedures for MySQL
Antony T Curtis
 

What's hot (18)

My sql tutorial-oscon-2012
My sql tutorial-oscon-2012My sql tutorial-oscon-2012
My sql tutorial-oscon-2012
 
wtf is in Java/JDK/wtf7?
wtf is in Java/JDK/wtf7?wtf is in Java/JDK/wtf7?
wtf is in Java/JDK/wtf7?
 
SenchaCon 2016: Theming the Modern Toolkit - Phil Guerrant
SenchaCon 2016: Theming the Modern Toolkit - Phil Guerrant   SenchaCon 2016: Theming the Modern Toolkit - Phil Guerrant
SenchaCon 2016: Theming the Modern Toolkit - Phil Guerrant
 
Polyglot Persistence
Polyglot PersistencePolyglot Persistence
Polyglot Persistence
 
Perl Stored Procedures for MySQL (2009)
Perl Stored Procedures for MySQL (2009)Perl Stored Procedures for MySQL (2009)
Perl Stored Procedures for MySQL (2009)
 
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDBUsing Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
 
SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
SenchaCon 2016: Modernizing the Ext JS Class System - Don GriffinSenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
 
Data Processing Inside PostgreSQL
Data Processing Inside PostgreSQLData Processing Inside PostgreSQL
Data Processing Inside PostgreSQL
 
My sql1
My sql1My sql1
My sql1
 
External Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLExternal Language Stored Procedures for MySQL
External Language Stored Procedures for MySQL
 
Clojure Deep Dive
Clojure Deep DiveClojure Deep Dive
Clojure Deep Dive
 
java
javajava
java
 
Flux: Apache Storm Frictionless Topology Configuration & Deployment
Flux: Apache Storm Frictionless Topology Configuration & DeploymentFlux: Apache Storm Frictionless Topology Configuration & Deployment
Flux: Apache Storm Frictionless Topology Configuration & Deployment
 
es6
es6es6
es6
 
Oracle adapters for Ruby ORMs
Oracle adapters for Ruby ORMsOracle adapters for Ruby ORMs
Oracle adapters for Ruby ORMs
 
Developing Applications with MySQL and Java for beginners
Developing Applications with MySQL and Java for beginnersDeveloping Applications with MySQL and Java for beginners
Developing Applications with MySQL and Java for beginners
 
MySQL
MySQLMySQL
MySQL
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2
 

Viewers also liked (6)

Starkus_2011
Starkus_2011Starkus_2011
Starkus_2011
 
Welcome to CEO
Welcome to CEOWelcome to CEO
Welcome to CEO
 
Robin hood and arthur
Robin hood and arthurRobin hood and arthur
Robin hood and arthur
 
Power point Hardware
Power point HardwarePower point Hardware
Power point Hardware
 
секція 2010 2011
секція 2010 2011секція 2010 2011
секція 2010 2011
 
Part6g
Part6gPart6g
Part6g
 

Similar to Lobos Introduction

Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
lennartkats
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
David Padbury
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
Inada Naoki
 

Similar to Lobos Introduction (20)

Slickdemo
SlickdemoSlickdemo
Slickdemo
 
Scala active record
Scala active recordScala active record
Scala active record
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with Clojure
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
 
Obevo Javasig.pptx
Obevo Javasig.pptxObevo Javasig.pptx
Obevo Javasig.pptx
 
10 Reasons to Start Your Analytics Project with PostgreSQL
10 Reasons to Start Your Analytics Project with PostgreSQL10 Reasons to Start Your Analytics Project with PostgreSQL
10 Reasons to Start Your Analytics Project with PostgreSQL
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
 
Solid and Sustainable Development in Scala
Solid and Sustainable Development in ScalaSolid and Sustainable Development in Scala
Solid and Sustainable Development in Scala
 
Sql lite android
Sql lite androidSql lite android
Sql lite android
 
Sqlapi0.1
Sqlapi0.1Sqlapi0.1
Sqlapi0.1
 
Intro to Spark and Spark SQL
Intro to Spark and Spark SQLIntro to Spark and Spark SQL
Intro to Spark and Spark SQL
 
No Coding Necessary: Building User Macros and Dynamic Reports Inside Confluen...
No Coding Necessary: Building User Macros and Dynamic Reports Inside Confluen...No Coding Necessary: Building User Macros and Dynamic Reports Inside Confluen...
No Coding Necessary: Building User Macros and Dynamic Reports Inside Confluen...
 
ClojureScript for the web
ClojureScript for the webClojureScript for the web
ClojureScript for the web
 

Recently uploaded

Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 

Recently uploaded (20)

Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutes
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
Demystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John StaveleyDemystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John Staveley
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
НАДІЯ ФЕДЮШКО БАЦ «Професійне зростання QA спеціаліста»
НАДІЯ ФЕДЮШКО БАЦ  «Професійне зростання QA спеціаліста»НАДІЯ ФЕДЮШКО БАЦ  «Професійне зростання QA спеціаліста»
НАДІЯ ФЕДЮШКО БАЦ «Професійне зростання QA спеціаліста»
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 

Lobos Introduction

  • 1. Lobos Introduction Presentation given to the Bonjure group on 2011/01/21.
  • 2. Outline ● Overview & basic concepts ● Past: history and development highlights ● Present: examples, project structure and architecture ● Future: migrations and declarative schema manipulation
  • 3. Overview Clojure code SQL Statement(s)* (create CREATE TABLE "users" ( (table :users "name" VARCHAR(100), (integer :id :auto-inc "id" SERIAL, :primary-key) CONSTRAINT "min_length" (varchar :name 100 :unique) CHECK (length("name") > 1), (check :min_length CONSTRAINT "users_unique_name" (> :length/name 1)))) UNIQUE ("name"), CONSTRAINT "users_primary_key_id" PRIMARY KEY ("id")) Note that the syntax is partially inspired by ActiveRecord::Migration *This example use the PostgreSQL backend.
  • 4. Basic Concepts ● Abstract Schema Definition: Used internally to represent a database schema. ● Action: Functions executing imperative SQL statements. ● AST: Intermediate database-agnostic representation of SQL statements.
  • 6. History ● Lobos is based on the original ClojureQL project which was based on SchemeQL. ● It's a complete rewrite of the DDL part. ● Lobos is less than a month old and a one-man effort for now.
  • 7. Development Highlights ● Uses most Clojure features and best practices. ● Namespace structure makes the project very modular. ● Bugs in Clojure code can be hard to diagnose, beware of laziness!
  • 9. Examples (use 'lobos.connectivity) (def pg {:classname "org.postgresql.Driver" :subprotocol "postgresql" :user "test" :password "test123" :subname "//localhost:5432/test"}) (open-global pg) (close-global) || (open-global :pg pg) (close-global :pg) You can specify a connection map (or global connection name) as the first argument of an action or use the global default connection.
  • 10. Examples All elements are constructed using functions or macros that yield Clojure data structures and thus are composable. Here we define some helpers: (use 'lobos.schema) (defn surrogate-key [table] (integer table :id :auto-inc :primary-key)) (defmacro tabl [name & elements] `(-> (table ~name (surrogate-key)) ~@elements)) (defn refer-to [table ptable] (let [cname (-> (->> ptable name butlast (apply str)) (str "_id") keyword)] (integer table cname [:refer ptable :id :on-delete :set-null])))
  • 11. Examples With the previously defined custom functions and macros we can define a more complex schema with less code... (use 'lobos.core) (defschema sample-schema :lobos (tabl :users (varchar :name 100 :unique) (check :name (> :length/name 1))) (tabl :posts (varchar :title 200 :unique) (text :content) (refer-to :users)) (tabl :comments (text :content) (refer-to :users) (refer-to :posts)))
  • 12. Examples Schemas created with defschema are functions returning an abstract schema! (create-schema sample-schema) (set-default-schema sample-schema) (drop (table :posts) :cascade) (drop-schema sample-schema :cascade) The cascade behavior works even in SQL Server which doesn't support that feature! Dropping a schema created with defschema makes the defined function return nil, so just pretend we didn't evaled that line! Warning: all uses of exclamation points in this slide are completely superfluous!
  • 13. Examples (alter :add (table :users (text :bio))) (alter :add (table :users (text :location) (text :occupation))) (alter :add (table :posts (check :content_limit (< :length/content 1337)))) (alter :modify (table :users (column :location [:default "somewhere"]))) (alter :drop (table :users (column :occupation))) (alter :rename (table :users (column :location :to :origin)))
  • 14. Any questions yet? Do we need a break?
  • 15. Project Structure ● Frontend  lobos.core  lobos.schema  lobos.connectivity ● Backend  lobos.compiler  lobos.ast  lobos.backends.* ● Analyzer  lobos.metadata  lobos.analyzer
  • 16. Project Structure connectivity core * analyzer schema utils metadata ast compiler backends
  • 17. Architecture ● Actions yield Abstract Schema Definitions ● Schema protocols build a AST(s) from ASDs ● The compiler (compile multi-method) generates the appropriate SQL statements from an AST. ● The analyzer constructs an abstract schema ASD from a real schema.
  • 18. Architecture (defrecord Table [name columns constraints options] Alterable Creatable Dropable (build-alter-statement [this action db-spec] (let [elements (map #(build-definition (second %) db-spec) (concat columns constraints))] (for [element elements] (AlterTableStatement. db-spec name action element)))) (build-create-statement [this db-spec] (CreateTableStatement. db-spec name (map #(build-definition (second %) db-spec) (concat columns constraints)))) (build-drop-statement [this behavior db-spec] (DropStatement. db-spec :table name behavior)))
  • 19. Architecture (def backends-hierarchy (atom (-> (make-hierarchy) (derive :h2 ::standard) (derive :mysql ::standard) (derive :postgresql ::standard) (derive :sqlite ::standard) (derive :sqlserver ::standard)))) (defmulti compile (fn [o] [(-> o :db-spec :subprotocol (or ::standard) keyword) (type o)]) :hierarchy backends-hierarchy) ... (defmethod compile [::standard AutoIncClause] [_] "GENERATED ALWAYS AS IDENTITY") ... (defmethod compile [:mysql AutoIncClause] [_] "AUTO_INCREMENT")
  • 21. Migrations Objectives: ● Could be written manually, like in ActiveRecord::Migration ● Could be automatically generated when actions are entered at the REPL ● Also automatically generated when declaratively changing a schema definition (see next slide)
  • 22. Declarative Schema Manipulation Say we are working on a database built from the following schema: (defschema sample-schema :lobos (table :users (varchar :name 100 :unique) (check :name (> :length/name 1))) ... Instead of imperatively issuing alter statements, wouldn't it be great to just change it? (defschema sample-schema :lobos (table :users (varchar :name 100 :unique) (text :bio) (check :name (> :length/name 1))) ...
  • 23. I need your help! Visit the project's github page: https://github.com/budu/lobos Any questions suggestions, comments or insults?
  • 24. Links Website: http://budu.github.com/lobos/ Code Repository: https://github.com/budu/lobos Issue Tracker: https://github.com/budu/lobos/issues Wiki: https://github.com/budu/lobos/wiki
  • 25. Acknowledgments Thanks (in alphabetical order) to: ● James Reeves (for Hiccup) ● Lau B. Jensen (for the old and new ClojureQLs) ● Meikel Brandmeyer (for working with me on the old ClojureQL) ● Michael Fogus (for Marginalia and "The Joy of Clojure" book) ● Phil Hagelberg (for Leiningen) ● Rich Hickey (for Clojure) ● Stephen C. Gilardi (for clojure.contrib.sql) Also thanks to all Clojure contributors and to its fantastic community!