Code Monkey home page Code Monkey logo

yesql's Introduction

Yesql

Yesql is an Elixir library for using SQL.

Rationale

You're writing Elixir You need to write some SQL.

One option is to use Ecto, which provides a sophisticated DSL for generating database queries at runtime. This can be convenient for simple use, but its abstraction only works with the simplest and common database features. Because of this either the abstraction breaks down and we start passing raw strings to Repo.query and fragment, or we will neglect these database features altogether.

So what's the solution? Keep the SQL as SQL. Have one file with your query:

SELECT *
FROM users
WHERE country_code = :country_code

...and then read that file to turn it into a regular Elixir function at compile time:

defmodule Query do
  use Yesql, driver: Postgrex, conn: MyApp.ConnectionPool

  Yesql.defquery("some/where/select_users_by_country.sql")
end

# A function with the name `users_by_country/1` has been created.
# Let's use it:
iex> Query.users_by_country(country_code: "gbr")
{:ok, [%{name: "Louis", country_code: "gbr"}]}

By keeping the SQL and Elixir separate you get:

  • No syntactic surprises. Your database doesn't stick to the SQL standard - none of them do - but Yesql doesn't care. You will never spend time hunting for "the equivalent Ecto syntax". You will never need to fall back to a fragment("some('funky'::SYNTAX)") function.
  • Better editor support. Your editor probably already has great SQL support. By keeping the SQL as SQL, you get to use it.
  • Team interoperability. DBAs and developers less familiar with Ecto can read and write the SQL you use in your Elixir project.
  • Easier performance tuning. Need to EXPLAIN that query plan? It's much easier when your query is ordinary SQL.
  • Query reuse. Drop the same SQL files into other projects, because they're just plain ol' SQL. Share them as a submodule.
  • Simplicity. This is a very small library, it is easier to understand and review than Ecto and similar.

When Should I Not Use Yesql?

When you need your SQL to work with many different kinds of database at once. If you want one complex query to be transparently translated into different dialects for MySQL, Oracle, Postgres etc., then you genuinely do need an abstraction layer on top of SQL.

Alternatives

We've talked about Ecto, but how does Yesql compare to $OTHER_LIBRARY?

eql is an Erlang library with similar inspiration and goals.

  • eql offers no solution for query execution, the library user has to implement this. Yesql offers a friendly API.
  • Being an Erlang library eql has to compile the queries at runtime, Yesql does this at compile time so you don't need to write initialisation code and store your queries somewhere.
  • eql requires the neotoma PEG compiler plugin, Yesql only uses the Elixir standard library.
  • Yesql uses prepared statements so query parameters are sanitised and are only valid in positions that your database will accept parameters. eql functions more like a templating tool so parameters can be used in any position and sanitisation is left up to the user.
  • A subjective point, but I believe the Yesql's implementation is simpler than eql's, while offering more features.

ayesql is another Elixir library, a bit more powerful than yesql:

yesql will keep your SQL queries closer to canonical SQL, but if you start finding it limiting or convoluted maybe it would be a good time to check out more powerful abstractions like ayesql or Ecto.

Development & Testing

createdb yesql_test
mix deps.get
mix test

Other Languages

Yesql rips off is inspired by Kris Jenkins' Clojure Yesql. Similar libraries can be found for many languages:

Language Project
C# JaSql
Clojure YeSPARQL
Clojure Yesql
Elixir ayesql
Erlang eql
Go DotSql
Go goyesql
JavaScript Preql
JavaScript sqlt
PHP YepSQL
Python Anosql
Ruby yayql

License

Copyright © 2018 Louis Pilfold. All Rights Reserved.

yesql's People

Contributors

lpil avatar chouzar avatar tschnibo avatar

Stargazers

Jeremy Huffman avatar ian avatar Ayodeji O. avatar  avatar Alex Kwiatkowski avatar  avatar Rainer Sai avatar  avatar Harshal avatar Mayel de Borniol avatar Leonardo Dutra avatar Nikita avatar Kasun Vithanage avatar Adam Wiggall avatar Khaja Minhajuddin avatar Preslav Rachev avatar  avatar Jonathan Urzua avatar Suss Buzz avatar Hissssst avatar  avatar Anicet Nougaret avatar Hoang Phan avatar Dax avatar Marcin Operacz avatar Victor Ray avatar Josh Taylor avatar Felipe Menegazzi avatar Ngoc Truong avatar Andrey Miskov avatar  avatar sitch avatar Quinn Wilton avatar  avatar Alessandro Iob avatar Radu Ciorba avatar Adel Nizamutdinov avatar Medson Oliveira avatar Ruthraiah Thulasi avatar Kyle Parisi avatar Sam Gaw avatar it-all.com avatar James Stephens avatar Mikal avatar Zdenek Kostal avatar Mat Garland avatar Zander Hill avatar Alex Castaño avatar Hao Wu avatar John Barker avatar Timo L. avatar Vanderlei Roberto Moretto avatar Tarak Bhavsar avatar Juri Hahn avatar Jason Axelson avatar David Bernheisel avatar Roman Pushkov avatar Anthony Doan avatar Chris Keathley avatar Evangelista avatar Yuuki TSUBOUCHI avatar Phillip Calvin avatar Gary Lo avatar Jason O avatar Alex de Sousa avatar Anon35251413454 avatar TristoSS avatar Simon Escobar Benitez avatar laserx avatar Milad avatar Tobiasz Małecki avatar Arpit Shah avatar Tymon Tobolski avatar Paul Straw avatar Philip Brown avatar Ben Smith avatar Hubert Łępicki avatar Sam avatar Cory Silva avatar Frans Oilinki avatar

Watchers

James Cloos avatar  avatar  avatar Vanderlei Roberto Moretto avatar

yesql's Issues

Can you use named parameters to pass in a list variable somehow?

e.g.

A common pattern might be...

SELECT u.id, u.name FROM user u
WHERE u.id IN (1, 2, 3)

I would ideally be able to define this like:

SELECT u.id, u.name FROM user u
WHERE u.id IN :user_list

and then call... select_user_name([3, 4, 5]) from Elixir.

is this possible? I find this is one of the main drawbacks of using raw sql as converting a list into parameters requires a million ?, ?, ? etc.

Thanks!

Support for multiple queries per file?

From the README and examples it seems (unlike clojure's yesql or even eql) only one query per file is supported. Was this a deliberate choice? or just not implemented as yet?

At the moment this is the only barrier for me to use this library exclusively as i foresee having to create many sql files for even a simple CRUD application with more than one db model/table.

Add Hexdocs

Hi @lpil Ipil it would be great to have a more "tutorial like" introduction in the docs. Similar to README.md but maybe a bit more thorough.

Would be happy to work on this :)

sql file transferred from linux to windows "\r" gets added to keyword with unspecific error

Hey,

Than you for your package!

Minor thing here... was just tinkering about and figured that if I have a empty line after the :keyword atom in the .sql file. And then transfer the whole think to windows, I suddenly get an error for ' not givenmissingParam) Required parameter ' :keyword.
Maybe the file was originally created on windows.

I found that the fetch_param function gets the key as :"keyword\r".

I guess one should not have trailing empty lines in the file anyways. But maybe one could still automatically remove the "\r" or give at least a more ideal warning.

Query.testquery([atc: "J02"])
param in fetch_param :"atc\r"
gives
not givenissingParam) Required parameter :atc
So at first I did not see that there was a "\r" parsed into the key.

I am an elixir beginner. And by no means an interoop specialist. Would it be ok to replace:
{:ok, sql, param_spec} = file_path |> File.read!() |> Yesql.parse()
with
{:ok, sql, param_spec} = file_path |> File.read!() |> String.replace("\r\n", "\n") |> Yesql.parse()
or does that have downsides for other operating systems or maybe more complex queries?
For my specific file this helps (beside of course deleting the control character...).

Many thanks and best regards
Tschnibo

Feature request

Hey, as already "commited" and messed around in the other issue. I wanted to ask if you would support customizable drivers.

Usecase:
I use your library with a patched Mssqlex for SAP-Hana and would like to use it again with Mssqlex for a Mssql db.

So maybe I could just rename the two Mssqlex Modules and add them as custom drivers.

As soon as my principle is tested with Mssqlex I'll create a separate PR again.

Thank you! And again, sorry for the mess!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.