Giter VIP home page Giter VIP logo

sqrl's Introduction

sqrl - fat-free version of squirrel - fluent SQL generator for Go

Non thread safe fork of squirrel. The same handy fluffy helper, but with extra letters removed :)

import "github.com/elgris/sqrl"

GoDoc Build Status

Requires Go 1.8 and higher

Inspired by

Why to make good squirrel lighter?

Ask benchmarks about that ;). Squirrel is good, reliable and thread-safe with it's immutable query builder. Although immutability is nice, it's resource consuming and sometimes redundant. As authors of dbr say: "100% of our application code was written without the need for this".

Why not to use dbr then?

Although, dbr's query builder is proven to be much faster than squirrel and even faster than sqrl, it doesn't have all syntax sugar. Especially I miss support of JOINs, subqueries and aliases.

Usage

sqrl is not an ORM., it helps you build SQL queries from composable parts. sqrl is non thread safe. SQL builders change their state, so using the same builder in parallel is dangerous.

It's very easy to switch between original squirrel and sqrl, because there is no change in interface:

import sq "github.com/elgris/sqrl" // you can easily use github.com/lann/squirrel here

users := sq.Select("*").From("users").Join("emails USING (email_id)")

active := users.Where(sq.Eq{"deleted_at": nil})

sql, args, err := active.ToSql()

sql == "SELECT * FROM users JOIN emails USING (email_id) WHERE deleted_at IS NULL"
sql, args, err := sq.
    Insert("users").Columns("name", "age").
    Values("moe", 13).Values("larry", sq.Expr("? + 5", 12)).
    ToSql()

sql == "INSERT INTO users (name,age) VALUES (?,?),(?,? + 5)"

Like squirrel, sqrl can execute queries directly:

stooges := users.Where(sq.Eq{"username": []string{"moe", "larry", "curly", "shemp"}})
three_stooges := stooges.Limit(3)
rows, err := three_stooges.RunWith(db).Query()

// Behaves like:
rows, err := db.Query("SELECT * FROM users WHERE username IN (?,?,?,?) LIMIT 3", "moe", "larry", "curly", "shemp")

Build conditional queries with ease:

if len(q) > 0 {
    users = users.Where("name LIKE ?", q)
}

MySQL-specific functions

sql, args, err := sq.Delete("a1", "a2").
    From("z1 AS a1").
    JoinClause("INNER JOIN a2 ON a1.id = a2.ref_id").
    Where("b = ?", 1).
    ToSql()
sql, args, err := sq.Delete("a1").
    Using("a2").
    Where("a1.id = a2.ref_id AND a2.num = ?", 42).
    ToSql()

PostgreSQL-specific functions

Package pg contains PostgreSQL specific operators.

sql, args, err := sq.Update("a1").
    Set("foo", 1).
    From("a2").
    Where("id = a2.ref_id AND a2.num = ?", 42).
    ToSql()
sql, args, err := sq.Delete("a1").
    Using("a2").
    Where("id = a2.ref_id AND a2.num = ?", 42).
    ToSql()
sql, args, err := Update("a").
    Set("foo", 1).
    Where("id = ?", 42).
    Returning("bar").
    ToSql()

JSON and JSONB use json.Marshal to serialize values and cast them to appropriate column type.

sql, args, err := sq.Insert("posts").
    Columns("content", "tags").
    Values("Lorem Ipsum", pg.JSONB([]string{"foo", "bar"})).
    ToSql()

Array serializes single and multidimensional slices of string, int, float32 and float64 values.

sql, args, err := sqrl.Insert("posts").
    Columns("content", "tags").
    Values("Lorem Ipsum", pg.Array([]string{"foo", "bar"})).
    ToSql()

License

Sqrl is released under the MIT License.

sqrl's People

Contributors

arsonox avatar coccodrillo avatar elgris avatar glaslos avatar godsboss avatar joeshaw avatar lann avatar lokhman avatar mcrayray avatar mjangda avatar ngdinhtoan avatar nizsheanez avatar rande avatar rangelreale avatar shaxbee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sqrl's Issues

Add RowsScanner interface

Currently it is impossible to fully unit test code that is using sqrl since Query method requires *sql.Rows as return value. I am proposing to add RowsScanner interface that would allow *sql.Rows to be replaced by another struct that implements required methods.

type Queryer interface {
    Query(query string, args ...interface{}) (RowsScanner, error)
}

As far as I can tell, RowsScanner could look something like this:

type RowsScanner interface {
    Columns() ([]string, error)
    Next() bool
    Close() error
    Err() error
    RowScanner
}

"Clone" on assignment?

Hello to everyone:

I know that sqrl is not thread safe, but: In a webservice context, What if on every request a cached pointer to an SelectBuilder is dereferenced and assigned to a variable?

Something like this:

var sqlSelect sqrl.Select("*").From("users") // *sqr.SelectBuilder
.
.
.
func calledOnEveryRequest() (error) {
query := *sqlSelect // Is "query" a completely new copy (deep copy) of sqlSelect value?
.
.
.
}

Many thanks in advance.

Add Lt, Gt, LtOrEq, GtOrEq

These methods were a recent addition and I found about it when i was migrating to sqrl these were missing. It's not a big deal, but since this has the same interface, I thought it'd be nice to have them. I will make a PR with those added.

escape reserved symbols

It would be nice to tell sqrl to escape column names for example "status" is a reserved symbol in mysql.

users := sq.Select("status").From("users").Join("emails USING (email_id)")
fmt.Println(users.ToSql())

output is:

SELECT status FROM users JOIN emails USING (email_id) [] <nil>

should be:

SELECT `status` FROM users JOIN emails USING (email_id) [] <nil>

Enable placeholders support in all query builder methods

Currently only Where method accepts args as placeholder values

func (b *SelectBuilder) Where(pred interface{}, args ...interface{}) *SelectBuilder {
    b.whereParts = append(b.whereParts, newWherePart(pred, args...))
    return b
}

Other methods like GroupBy can not accept placeholdered data

// GroupBy adds GROUP BY expressions to the query.
func (b *SelectBuilder) GroupBy(groupBys ...string) *SelectBuilder {
    b.groupBys = append(b.groupBys, groupBys...)
    return b
}

Please add placeholders support to these methods to provide means for building rich SQL statements.

SelectFrom args with wrong placeholder values

The query params inside a FromSelect are numbered independently from the whole query, so:

psql.Update(`mytable`).
		Set("name", "newname").
                FromSelect(psql.Select("column").From("anothertable").Where(sq.Eq{"column": 3})).
                Where(sq.Eq{"name": "oldname"})

Args will be ["newname", "oldname", 3], but query string will be:

update mytable set name = $1
select column from anothertable where column = $1
where name = $2

Correct should be:

update mytable set name = $1
select column from anothertable where column = $3
where name = $2

FromSelect should change the placeholder count to start from where the parent Update ends

Invalid DELETE query with alias

For example: DELETE a FROM A a JOIN B b ON a.c = b.c ....
sqrl.Delete("s").From("A a").Join("B b ON a.c = b.c). ...

Due to delete statement builder handling in sqrl.Delete(...), if only a single element (remains after filtering) it is pushed to the From-part instead. Causing an invalid query to be generated at least for MySQL: DELETE FROM A a JOIN B b ON a.c = b.c ....

Commit 2178fbc00 does not build

When trying to build since commit 2178fbc I get this error:

../../../github.com/elgris/sqrl/stmtcacher.go:61: stmt.ExecContext undefined (type *sql.Stmt has no field or method ExecContext)
../../../github.com/elgris/sqrl/stmtcacher.go:61: not enough arguments to return
../../../github.com/elgris/sqrl/stmtcacher.go:69: stmt.QueryContext undefined (type *sql.Stmt has no field or method QueryContext)
../../../github.com/elgris/sqrl/stmtcacher.go:69: not enough arguments to return
../../../github.com/elgris/sqrl/stmtcacher.go:77: stmt.QueryRowContext undefined (type *sql.Stmt has no field or method QueryRowContext)
../../../github.com/elgris/sqrl/stmtcacher.go:109: cannot use db (type *sql.DB) as type Preparer in argument to NewStmtCacher:
	*sql.DB does not implement Preparer (missing PrepareContext method)

How to create dynamic WHERE clause

Hi,

Is there support for dynamic where clauses? I could not find any documentation about how to do that. In my case I need to add AND'd conditions with nested OR conditions conditionally, to get something like:
WHERE x=? AND (foo>=? OR bar> ?) AND (bar> ?)

I've tried to create an []sq.Sqlizer and add the OR-expressions in there, then feed that to SelectBuilder.Where() but it fails with the message

converting Exec argument # 1's type: unsupported type []sqrl.Sqlizer, a slice

Ideally there is some kind of ConditionBuilder for this I guess.

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.