Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/adamcooke/sqb
👷♀️ A very simple but effective SQL query builder
https://github.com/adamcooke/sqb
query-builder ruby sql
Last synced: 9 days ago
JSON representation
👷♀️ A very simple but effective SQL query builder
- Host: GitHub
- URL: https://github.com/adamcooke/sqb
- Owner: adamcooke
- License: mit
- Created: 2018-02-26T12:40:47.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2020-02-24T12:56:39.000Z (over 4 years ago)
- Last Synced: 2024-11-02T12:34:20.531Z (16 days ago)
- Topics: query-builder, ruby, sql
- Language: Ruby
- Homepage:
- Size: 110 KB
- Stars: 6
- Watchers: 3
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: MIT-LICENSE
Awesome Lists containing this project
README
# SQB (SQL Query Builder)
[![Build Status](https://travis-ci.org/adamcooke/sqb.svg?branch=master)](https://travis-ci.org/adamcooke/sqb) [![Gem Version](https://badge.fury.io/rb/sqb.svg)](https://badge.fury.io/rb/sqb)
This is a gem that allows you to construct SQL queries from a simple Ruby DSL. There are lots of gems like this around but I haven't yet found one that I really enjoy using that supports things like ORs or various different operators nicely. This isn't a perfect solution but is very handy for quickly generating queries.
## Installation
```ruby
gem 'sqb'
```## Selecting data
To get started just create yourself a `SQB::Select` object and provide the base table name.
```ruby
query = SQB::Select.new(:posts)
```When you've done all the operations on the query that you wish to do (see below) you can extract the finished SQL query and prepared arguments for passing to a database client.
```ruby
# Return the SQL query itself
query.to_sql# Return any arguments needed for the query
query.prepared_arguments# For example with the MySQL2 client you might do this...
statement = mysql.prepare(query.to_sql)
statement.execute(*query.prepared_arguments)
statement.close
```### Filtering
The most common thing you'll want to do is filter the data returned which means using `WHERE`. You can do any of the following to filter the data returned.
```ruby
# The most basic equality operators
query.where(:title => "Hello world!")
query.where(:title => {:equal => "Hello world!"})
query.where(:title => {:not_equal => "Hello world!"})# Greater than or less than
query.where(:comments_count => {:greater_than => 100})
query.where(:comments_count => {:less_than => 1})
query.where(:comments_count => {:greater_than_or_equal_to => 100})
query.where(:comments_count => {:less_than_or_equal_to => 1})# Like/Not like
query.where(:body => {:like => "Hello world!"})
query.where(:body => {:not_like => "Hello world!"})# In/not in an array
query.where(:author_id => [1,2,3,4])
query.where(:author_id => {:in => [1,2,3,4]})
query.where(:author_id => {:not_in => [1,2,3,4]})# Nulls
query.where(:markdown => nil)
query.where(:markdown => {:not_equal => nil})# Sub-queries in where queries
other_query = SQB::Select.new(:comments)
other_query.where(post_id: SQB.column(:posts => :id))
other_query.select(:count, :function => 'COUNT')
query.where(other_query => {:greater_than => 10})
```By default all filtering operations will be joined with ANDs. You can use OR if needed.
```ruby
query.or do
query.where(:author => "Sarah Smith")
query.where(:author => "John Jones")
end
```### Selecting columns
By default, all the columns on your main table will be selected with a `*` however you may not wish to get them all or you may wish to use functions to get other data.
```ruby
query.column(:title)
query.column(:id, :function => 'COUNT', :as => 'count')# You can do more complex function operations
query.column(:amount, :function => SQB.safe('IFNULL(SUM($$), 0.0))', :as => 'total')# Subqueries can be used in columns too
other_query = SQB::Select.new(:comments)
other_query.where(post_id: SQB.column(:posts => :id))
other_query.select(:count, :function => 'COUNT')
query.column(other_query, :as => :comments_count)# If you have already added columns and wish to replace them all with a new one
query.column!(:other_column)# You can choose to select all columns too
query.column(SQB::STAR)
```### Specifying orders
You can add fields that you wish to order by as either ascending or decending.
```ruby
query.order(:posted_at)
query.order(:posted_at, :asc)
query.order(:posted_at, :desc)# If you have already added some orders and wish to replace them with a new field
query.order!(:last_comment_posted_at, :desc)# To remove all ordering
query.no_order!
```### Limiting the returned records
You can specify limits and offsets easily
```ruby
query.limit(30)
query.offset(120)
```### Joining with other tables
To join with other tables you can do so easily with the `join` methods.
```ruby
query.join(:comments, :post_id)
query.join(:comments, :post_id, :name => :comments)
```By default, this will join with the table (by default `INNER JOIN`) but won't return any data. You'll likely want to add some conditions and/or some columns to return.
```ruby
query.join(:comments, :post_id, :columns => [:content])# You can specify the type as either :inner, :left or :right
query.join(:users, [:id, :author_id], :name => :author, :type => :left)# This will join users where the user `id` matches the `author_id` in the base table
query.join(:users, [:id, :author_id], :name => :author)# This will join to a different join rather than the base table
query.join(:users, [:id, {user_joins: :user_id}])# You can add additional join conditions like so. The additional conditions will be
# added to the `ON` part of the join along with the key join.
query.join(:comments, :post_id, :conditions => {:spam => true})# You can also use the existing where and column methods to add joins to these tables
query.column({:comments => :spam})
query.where({:comments => :spam} => {:not_equal => true})# Unless a name is provided with the join, you'll be able to access the join as
# [table_name]_0 (where 0 is an index for the number of joins for that table
# starting with 0).
```### Grouping
You can, of course, group your data too
```ruby
query.group_by(:author_id)
query.column(:author_id)
query.column(:count, :function => 'COUNT', :as => 'count')
```### Distinct
To only return distinct rows for your dataset:
```ruby
query.distinct
```## Inserting data
The INSERT query is one of the less friendly ones but SQB makes light work of it.
```ruby
query = SQB::Insert.new(:posts)
query.value(:title => 'Hello world!', :author_id => 1)
```## Updating data
SQB supports crafting UPDATE queries too. You can use the same options for `where` as when selecting data (see above). The `set` method accepts a hash of all values that you wish to update (it can be called multiple times to add additional values).
```ruby
query = SQB::Update.new(:posts)
query.set(:title => 'Hello world!')
query.where(:id => 10)
```## Deleting data
SQB can write you some lovely DELETE queries too. You can use `where`, `limit` and `order` to limit which records are deleted.
```ruby
query = SQB::Delete.new(:posts)
query.where(:id => 10)
query.limit(10)
query.order(:id => :desc)
```## Other options
### Specifying a database
You can specify the name of a database that you wish to query. By default, no database name will be included in the query.
```ruby
query = SQB::Query.new(:posts, :database_name => :my_blog)
```### Inserting arbitary strings
There are occasions where you need to break free from constraints. You can do that by passing strings through the `SQB.safe(string)` method. This will avoid any escaping or clever magic by SQB and the string provided will simply be inserted in the query as appropriate.
```ruby
query.column(SQB.safe('SUM(CEILING(duration / 60))'))
# or
query.where(SQB.safe('IF(LENGTH(excerpt) > 0, excerpt, description)') => {:equal => "Llamas!"})
```