{"id":13788450,"url":"https://github.com/budu/lobos","last_synced_at":"2025-04-04T09:09:43.984Z","repository":{"id":1250106,"uuid":"1188672","full_name":"budu/lobos","owner":"budu","description":"A library to create and manipulate SQL database schemas with migrations support.","archived":false,"fork":false,"pushed_at":"2016-11-18T20:46:11.000Z","size":2236,"stargazers_count":266,"open_issues_count":35,"forks_count":56,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-26T19:42:07.292Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://budu.github.com/lobos/","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/budu.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-12-21T23:12:45.000Z","updated_at":"2025-03-23T03:07:15.000Z","dependencies_parsed_at":"2022-07-18T16:28:59.980Z","dependency_job_id":null,"html_url":"https://github.com/budu/lobos","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/budu%2Flobos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/budu%2Flobos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/budu%2Flobos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/budu%2Flobos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/budu","download_url":"https://codeload.github.com/budu/lobos/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247149502,"owners_count":20891954,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T21:00:46.793Z","updated_at":"2025-04-04T09:09:43.964Z","avatar_url":"https://github.com/budu.png","language":"Clojure","funding_links":[],"categories":["databases","Structural Migrations"],"sub_categories":[],"readme":"# Lobos\n\n[![Continuous Integration status](https://secure.travis-ci.org/budu/lobos.png)](http://travis-ci.org/budu/lobos)\n\n**Lobos** is a SQL database schema manipulation and migration library\nwritten in [Clojure]. It currently support supports H2, MySQL,\nPostgreSQL, SQLite and SQL Server.\n\nIf you have any questions, please join the [mailing list].\n\n## Features\n\n * A comprehensive data definition language DSL.\n * Migrations for schema changes.\n * An analyzer to query the schema.\n\n## Installation\n\nLobos is available through [Clojars].\n\nFor the latest release, in Cake/Leiningen, use:\n\n#### `project.clj`\n```clojure\n:dependencies [[lobos \"1.0.0-beta3\"]]\n```\n\nor in Maven:\n\n#### `pom.xml`\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003elobos\u003c/groupId\u003e\n  \u003cartifactId\u003elobos\u003c/artifactId\u003e\n  \u003cversion\u003e1.0.0-beta3\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Usage\n\nHere's a small tutorial on how to use Lobos.\n\n### Basic Example\n\nStart by creating a new project with your preferred tool. Assuming a\n[Leiningen] compatible project file, add **Lobos** and a database driver\nto the `dependencies` section:\n\n```clojure\n:dependencies [...\n               [lobos \"1.0.0-beta1\"]\n               [postgresql \"9.1-901.jdbc4\"]]\n```\n\nOnce you have your dependencies downloaded, open up a REPL and load\nthese namespaces:\n\n```clojure\n(use '(lobos connectivity core schema))\n```\n\nYou'll get warnings about some already defined function, just ignore\nthis for now.\n\nThen you'll need to create a connection, the following snippet define\none and makes it the default global connection:\n\n```clojure\n(def db\n     {:classname \"org.postgresql.Driver\"\n      :subprotocol \"postgresql\"\n      :user \"test\"\n      :password \"test123\"\n      :subname \"//localhost:5432/test\"})\n\n(open-global db)\n```\n\nYou can now send DDL statements (called *actions*) directly like this:\n\n```clojure\n(create (table :users (integer :id :unique)))\n```\n\nYou can omit the connection altogether. In that case, actions will use\nthe connection bound by `lobos.connectivity/with-connection` or the\ndefault one.\n\n```clojure\n(drop (table :users))\n```\n\nNow that you've tested the basics of **Lobos** at the REPL, let's try\nout a more real-world example.\n\n### Real-world Example\n\nBy *real-world*, I'm not talking about a production ready database\nschema, it's about how to integrate **Lobos** into your real\nprojects. We'll continue using the previously created test project, but\nthis time we'll use files. In your `src/` directory, create a directory\nnamed `lobos` and a file called `config.clj` inside it.\n\n#### `src/lobos/config.clj`\n```clojure\n(ns lobos.config\n  (:use lobos.connectivity))\n\n(def db\n  {:classname \"org.postgresql.Driver\"\n   :subprotocol \"postgresql\"\n   :user \"test\"\n   :password \"test123\"\n   :subname \"//localhost:5432/test\"})\n\n(open-global db)\n```\n\nNext, we'll see how to create helpers that will show the composable\nnature of the **Lobos** DSL. This part is entirely optional.\n\nAdd a new file called `helpers.clj`\n\n#### `src/lobos/helpers.clj`\n```clojure\n(ns lobos.helpers\n  (:refer-clojure :exclude [bigint boolean char double float time])\n  (:use (lobos schema)))\n```\n\nThe above namespace declaration exclude some `clojure.core` definitions\nthat clashes with data-type functions, this prevents warnings from being\nshown.\n\nEvery schema element definition is a simple function that return an\nintermediate representation that abstract real database schema element.\nThis allow you to make your own functions (and macros) that can help\ndefine a database schema more concisely.\n\nNow, let's define a bunch of useful helpers:\n\n#### `src/lobos/helpers.clj`\n```clojure\n(defn surrogate-key [table]\n  (integer table :id :auto-inc :primary-key))\n\n(defn timestamps [table]\n  (-\u003e table\n      (timestamp :updated_on)\n      (timestamp :created_on (default (now)))))\n\n(defn refer-to [table ptable]\n  (let [cname (-\u003e (-\u003e\u003e ptable name butlast (apply str))\n                  (str \"_id\")\n                  keyword)]\n    (integer table cname [:refer ptable :id :on-delete :set-null])))\n```\n\nThe first one add a standardized surrogate key called `id` to the\nspecified table. The second takes a table definition and add two\ngenerally useful columns to it. Finally, the third one create a\nforeign-key column to another table given its name. We can use these\nhelpers in the same way as already existing column definition functions.\n\nTo wrap it up, we'll add a macro that we'll use instead of the included\n`table` macro. It will help us create tables which implicitly include a\nsurrogate key and the timestamp columns.\n\n#### `src/lobos/helpers.clj`\n```clojure\n(defmacro tbl [name \u0026 elements]\n  `(-\u003e (table ~name)\n       (timestamps)\n       ~@(reverse elements)\n       (surrogate-key)))\n```\n\nWe have everything set up in place to create our first migrations, so\nlet's do that.\n\n### Migrations\n\nBy default all migrations are kept in the `lobos.migrations`\nnamespace. It'll get automatically loaded by migration commands, so\nthere's no need to load it yourself. Thus, to use another namespace you\nmust change the `lobos.migration/*migrations-namespace*` dynamic\nvariable. This is a normal Clojure source file so if you prefer having\nonly one migration per file, just do that and require these files in the\nmigrations namespace.\n\n#### `src/lobos/migrations.clj`\n```clojure\n(ns lobos.migrations\n  (:refer-clojure :exclude [alter drop\n                            bigint boolean char double float time])\n  (:use (lobos [migration :only [defmigration]] core schema\n               config helpers)))\n```\n\nMigrations are defined using the `defmigration` macro which is composed\nof two bodies, one making whatever changes you want to do, the other\nreverting those changes.\n\n#### `src/lobos/migrations.clj`\n```clojure\n(defmigration add-users-table\n  (up [] (create\n          (tbl :users\n            (varchar :name 100 :unique)\n            (check :name (\u003e (length :name) 1)))))\n  (down [] (drop (table :users))))\n\n(defmigration add-posts-table\n  (up [] (create\n          (tbl :posts\n            (varchar :title 200 :unique)\n            (text :content)\n            (refer-to :users))))\n  (down [] (drop (table :posts))))\n\n(defmigration add-comments-table\n  (up [] (create\n          (tbl :comments\n            (text :content)\n            (refer-to :users)\n            (refer-to :posts))))\n  (down [] (drop (table :comments))))\n```\n\nEach migrations must have a unique name that will be used by **Lobos**\nto figure out which ones have been applied.\n\nTo apply all pending migrations, use the `migrate` function in a REPL:\n\n```clojure\n(migrate)\n;=\u003e add-users-table\n;=\u003e add-posts-table\n;=\u003e add-comments-table\n```\n\nThis function can take a bunch of migration names in which case it will\nonly apply those.\n\nIf, for some reason, you need to rollback some migrations, use the aptly\nnamed `rollback` function:\n\n```clojure\n(rollback)\n;=\u003e add-comments-table\n```\n\nBy default it will rollback only the most recently applied migration. It\ncan also take migration names, an integer or the `:all` keyword and\nperform the appropriate rollback.\n\n### Analyzer\n\nLobos includes a database analyzer which use the database meta-data or\ninformation schema to construct an abstract schema definition from an\nactual database schema.\n\nHere's an interactive session that show some possible uses:\n\n```clojure\n(use 'lobos.analyzer)\n;=\u003e nil\n(-\u003e (analyze-schema) :tables keys)\n;=\u003e (:comments :lobos_migrations :posts :users)\n(-\u003e (analyze-schema) :tables :users :columns :name :data-type :name)\n;=\u003e :varchar\n(-\u003e (analyze-schema) :tables :posts :constraints :posts_unique_title :columns)\n;=\u003e [:title]\n```\n\n### Documentation\n\nFor more detailed information on **Lobos**, please refer to the\n[documentation].\n\n## License\n\nDistributed under the [Eclipse Public License], the same as Clojure.\n\n\n[Clojure]:                http://clojure.org/\n[mailing list]:           http://groups.google.com/group/lobos-library\n[Clojars]:                http://clojars.org/lobos\n[Leiningen]:              https://github.com/technomancy/leiningen\n[Eclipse Public License]: http://budu.github.com/lobos/epl-v10.html\n[documentation]:          http://budu.github.com/lobos/documentation.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbudu%2Flobos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbudu%2Flobos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbudu%2Flobos/lists"}