All Projects → swlkr → oksql

swlkr / oksql

Licence: EPL-1.0 License
An easy clojure postgres library

Programming Languages

clojure
4091 projects
Makefile
30231 projects

Projects that are alternatives of or similar to oksql

Ebean
Ebean ORM
Stars: ✭ 1,172 (+1598.55%)
Mutual labels:  postgres, jdbc
Scala Db Codegen
Scala code/boilerplate generator from a db schema
Stars: ✭ 49 (-28.99%)
Mutual labels:  postgres, jdbc
Requery
requery - modern SQL based query & persistence for Java / Kotlin / Android
Stars: ✭ 3,071 (+4350.72%)
Mutual labels:  postgres, jdbc
Quill
Compile-time Language Integrated Queries for Scala
Stars: ✭ 1,998 (+2795.65%)
Mutual labels:  postgres, jdbc
PGTools
Инструменты обслуживания и разработки для PostgreSQL, а также другие интересности
Stars: ✭ 37 (-46.38%)
Mutual labels:  postgres
OpenAM
OpenAM is an open access management solution that includes Authentication, SSO, Authorization, Federation, Entitlements and Web Services Security.
Stars: ✭ 476 (+589.86%)
Mutual labels:  jdbc
eventide-postgres
Event Sourcing and Microservices Stack for Ruby
Stars: ✭ 92 (+33.33%)
Mutual labels:  postgres
php-jdbc-bridge
Service and library to allow a PHP application to interface with a database via JDBC
Stars: ✭ 20 (-71.01%)
Mutual labels:  jdbc
jdbdt
JDBDT: Java Database Delta Testing
Stars: ✭ 12 (-82.61%)
Mutual labels:  jdbc
besu-exflo
A plugin for the Besu enterprise-grade Ethereum client with the aim of making it easier to extract chain data into a variety of different data stores and processing pipelines.
Stars: ✭ 16 (-76.81%)
Mutual labels:  postgres
walrus
Applying RLS to PostgreSQL WAL
Stars: ✭ 59 (-14.49%)
Mutual labels:  postgres
vok-orm
Mapping rows from a SQL database to POJOs in its simplest form
Stars: ✭ 13 (-81.16%)
Mutual labels:  jdbc
nest-blog-api
Blog Web API with NestJs, Postgres, and Sequelize ORM
Stars: ✭ 69 (+0%)
Mutual labels:  postgres
ptrack
Block-level incremental backup engine for PostgreSQL
Stars: ✭ 21 (-69.57%)
Mutual labels:  postgres
node-backend-template
A template for NodeJS backend projects
Stars: ✭ 19 (-72.46%)
Mutual labels:  postgres
lighthouse
Easy clojure relational database queries, migrations and connection pooling
Stars: ✭ 19 (-72.46%)
Mutual labels:  postgres
nodejs-with-postgres-api-example
k8s course example - node.js app with Postgres, Hapi.js and Swagger
Stars: ✭ 59 (-14.49%)
Mutual labels:  postgres
pg credereum
Prototype of PostgreSQL extension bringing some properties of blockchain to the relational DBMS
Stars: ✭ 52 (-24.64%)
Mutual labels:  postgres
eslint-plugin-sql
SQL linting rules for ESLint.
Stars: ✭ 56 (-18.84%)
Mutual labels:  postgres
rxkotlin-jdbc
Fluent RxJava JDBC extension functions for Kotlin
Stars: ✭ 27 (-60.87%)
Mutual labels:  jdbc

oksql

oksql is a library for using postgres.

Usage

Add [oksql "1.3.2"] to your :dependencies in your project.clj

or

Add oksql {:mvn/version "1.3.2"} to your deps.edn file

Then, create a .sql file in your resources/sql folder like this one for example:

-- items.sql

-- name: fetch
-- fn: first
select *
from items
where id = :id

-- name: all
select *
from items
order by created_at desc

-- name: insert
-- fn: first
insert into items (id, name, created_at)
values (:id, :name, :created_at)
returning *

-- name: update
-- fn: first
update items
set name = :name
where id = :id
returning *

-- name: delete
-- fn: first
delete
from items
where id = :id
returning *

Then create a file to wire up your queries and you're done!

(ns your-project.models.items
  (:require [oksql.core :as oksql])
  (:refer-clojure :exclude [update]))

(def db {:connection-uri "jdbc:postgresql://localhost:5432/your_project_db"})

(def query (partial oksql/query db))

(defn all []
  (query :items/all))

(defn fetch [id]
  (query :items/fetch {:id id}))

(defn create [{:keys [name created-at]}]
  (query :items/insert {:name name
                        :created-at created-at})) ; implicit! kebab -> snake case

(defn update [id m]
  (query :items/update (merge {:id id} m)))

(defn delete [id]
  (query :items/delete {:id id}))

A real advantage to this code (which can be generated statically) over the alternatives is that you can add your own validation logic before and after these functions and you get go to definition since there aren't any macros generating functions for you.

A good example of this:

(ns your-project.models.users
  (:require [oksql.core :as oksql]))

(defn validate [user]
  (if (contains? user :email)
    user
    (throw (Exception. "Email required"))))

(defn insert [m]
  (let [user (validate m)]
    (oksql/query :items/insert m)))

So I know what you're thinking, man that sucks to keep the super simple write sql parts (insert/update/delete) in sync every time I make a change to a table. Well.

; namespace keyword corresponds to db schema name
; public by default, just like postgres
(oksql/update db :items {:name "update name"} :items/where {:id 123})

(oksql/insert db :items {:name "new item"})

(oksql/delete db :items :items/where {:id 123})

So to review, oksql is kind of an ORM now, but not really! Only for writes if you want them.

You still have the full power of sql at your disposal, but for writing, it's kind of unnecessary. Here are the four functions again:

(ns your-project.models.items
  (:require [oksql.core :as oksql])
  (:refer-clojure :exclude [update]))

(def db {:connection-uri "jdbc:postgresql://localhost:5432/your_project_db"})

(def query (partial oksql/query db))

(defn all []
  (query :items/all))

(defn fetch [id]
  (query :items/fetch {:id id}))

(defn create [m]
  (oksql/insert db :items m))

(defn update [id m]
  (oksql/update db :items m :items/where {:id id}))

(defn delete [id]
  (oksql/delete db :items :items/where {:id id}))

Why

The default for interacting with postgres from clojure without a library looks like this

(def db {:connection-uri "jdbc:postgresql://localhost:5432/items_db"})
(jdbc/query db ["select items.id, items.name, items.created_at from items where id = ?" 123])

It's not too bad with a short query, but you can imagine several joins and many to many relationships getting out of hand. Plus there probably isn't any syntax highlighting in your editor for sql strings in a .clj file.

So you might graduate to something like this

(select item
  (fields :id :name :created_at)
  (where {:id 123}))

It's a lot nicer syntactically, but you're now writing a sql dsl, not sql. So you have to know not only sql but a clojure sql dsl which will eventually not have the thing you're looking for.

So, fed up with these things and probably more, yesql was born. Yesql basically solved my problems and I've been using it for the past two years on all of my projects. There are a few problems with yesql outlined in a fork here, jeesql.

jeesql solved most of my problems with yesql:

  • No instaparse dependency
  • No way to specify that you just want a single row

Unfortunately it added some stuff that I didn't really need:

  • Positional arguments
  • Various query attributes

I also didn't like that I couldn't "go to definition" with defqueries since it generated the functions with a macro. I'd rather just take a page from rails' book and generate the code statically and have it sitting in files, at least then it's easy to see and change it later. So those are the main differences from yesql, hugsql, and jeesql:

  • No defqueries macro
  • Simple results fn support (-- fn: first) support and that's it
  • No symbolic representation of returning *, just declare it explicitly
  • Implicit! Conversion of snake case to kebab case to and from the database!

Inspiration

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].