Skip to content

Commit

Permalink
v0.2.0
Browse files Browse the repository at this point in the history
* Changed `CrudExec` to not wrap driver errors in a GoquError #2
* Added ability to use a dataset in an `Ex` map or `Eq` expression without having to use `In` #3
   * `db.From("test").Where(goqu.Ex{"a": db.From("test").Select("b")})`
* Updated readme with links to [`DefaultAdapter`](https://godoc.org/github.com/doug-martin/goqu#DefaultAdapter)
  • Loading branch information
doug-martin committed Mar 11, 2015
1 parent 6755f41 commit 421dbb3
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 13 deletions.
7 changes: 7 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## v0.2.0

* Changed `CrudExec` to not wrap driver errors in a GoquError [#2](https://github.com/doug-martin/goqu/issues/2)
* Added ability to use a dataset in an `Ex` map or `Eq` expression without having to use `In` [#3](https://github.com/doug-martin/goqu/issues/3)
* `db.From("test").Where(goqu.Ex{"a": db.From("test").Select("b")})`
* Updated readme with links to [`DefaultAdapter`](https://godoc.org/github.com/doug-martin/goqu#DefaultAdapter)

## v0.1.1

* Added SQLite3 adapter [#1](https://github.com/doug-martin/goqu/pull/1) - [@mattn](https://github.com/mattn)
Expand Down
44 changes: 35 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,27 @@
\__, |\___/ \__, |\__,_|
|___/ |_|
```
[![GitHub tag](https://img.shields.io/github/tag/doug-martin/goqu.svg?style=flat)](https://github.com/doug-martin/goqu/releases)
[![wercker status](https://app.wercker.com/status/7eec67205c1ce1cc96ef81664f21256b/s "wercker status")](https://app.wercker.com/project/bykey/7eec67205c1ce1cc96ef81664f21256b)
[![GoDoc](https://godoc.org/github.com/doug-martin/goqu?status.png)](http://godoc.org/github.com/doug-martin/goqu)
[![GoCover](http://gocover.io/_badge/github.com/doug-martin/goqu)](http://gocover.io/github.com/doug-martin/goqu)
[![Join the chat at https://gitter.im/doug-martin/goqu](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/doug-martin/goqu?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

`goqu` is an expressive SQL builder

* [Basic](#basics)
* [Expressions](#expressions)
* [Complex Example](#complex-example)
* [Querying](#querying)
* [Dataset](#dataset)
* [Database](#database)
* [Transactions](#transactions)
* [Logging](#logging)
* [Adapters](#adapters)
* [Contributions](#contributions)
* [Changelog](https://github.com/doug-martin/goqu/tree/master/HISTORY.md)


This library was built with the following goals:

* Make the generation of SQL easy and enjoyable
Expand All @@ -35,6 +50,7 @@ or hooks I would recommend looking at some of the great ORM libraries such as:
* [gorm](https://github.com/jinzhu/gorm)
* [hood](https://github.com/eaigner/hood)

<a name="basics"></a>
## Basics

In order to start using goqu with your database you need to load an adapter. We have included some adapters by default.
Expand Down Expand Up @@ -84,6 +100,7 @@ SELECT * FROM "user" WHERE "id" = 10
SELECT * FROM "user" WHERE "id" = $1
```

<a name="expressions"></a>
### Expressions

`goqu` provides an idiomatic DSL for generating SQL however the Dataset only provides the the different clause methods (e.g. Where, From, Select), most of these clause methods accept Expressions(with a few exceptions) which are the building blocks for your SQL statement, you can think of them as fragments of SQL.
Expand Down Expand Up @@ -254,7 +271,7 @@ Output:
```sql
SELECT * FROM "test" WHERE ((("col1" IS NULL) AND ("col2" IS TRUE)) OR (("col3" IS NULL) AND ("col4" IS FALSE)) OR "col"::TEXT = "other_col"::TEXT)
```

<a name="complex-example"></a>
### Complex Example

Using the Ex map syntax
Expand Down Expand Up @@ -319,10 +336,12 @@ HAVING (AVG("test3"."age") > 10)
ORDER BY "test"."created" DESC NULLS LAST
```

### Querying
<a name="querying"></a>
## Querying

goqu also has basic query support through the use of either the Database or the Dataset.

<a name="dataset"></a>
### Dataset

* [`ScanStructs`](http://godoc.org/github.com/doug-martin/goqu#Dataset.ScanStructs) - scans rows into a slice of structs
Expand Down Expand Up @@ -474,6 +493,7 @@ if err := delete.ScanVals(&ids); err != nil{
}
```

<a name="database"></a>
### Database

The Database also allows you to execute queries but expects raw SQL to execute. The supported methods are
Expand All @@ -488,7 +508,8 @@ The Database also allows you to execute queries but expects raw SQL to execute.
* [`ScanVal`](http://godoc.org/github.com/doug-martin/goqu#Database.ScanVal)
* [`Begin`](http://godoc.org/github.com/doug-martin/goqu#Database.Begin)

## Transactions
<a name="transactions"></a>
### Transactions

`goqu` has builtin support for transactions to make the use of the Datasets and querying seamless

Expand Down Expand Up @@ -519,7 +540,7 @@ The [`TxDatabase`](http://godoc.org/github.com/doug-martin/goqu/#TxDatabase) al
* [`Rollback`](http://godoc.org/github.com/doug-martin/goqu#TxDatabase.Rollback)
* [`Wrap`](http://godoc.org/github.com/doug-martin/goqu#TxDatabase.Wrap)

### Wrap
#### Wrap

The [`TxDatabase.Wrap`](http://godoc.org/github.com/doug-martin/goqu/#TxDatabase.Wrap) is a convience method for automatically handling `COMMIT` and `ROLLBACK`

Expand All @@ -543,6 +564,7 @@ if err != nil{
}
```

<a name="logging"></a>
## Logging

To enable trace logging of SQL statments use the [`Database.Logger`](http://godoc.org/github.com/doug-martin/goqu/#Database.Logger) method to set your logger.
Expand All @@ -552,17 +574,20 @@ To enable trace logging of SQL statments use the [`Database.Logger`](http://godo
**NOTE** If you start a transaction using a database your set a logger on the transaction will inherit that logger automatically


<a name="adapters"></a>
## Adapters

Adapters in goqu are the foundation of building the correct SQL for each DB dialect.

Between most dialects there is a large portion of shared syntax, for this reason we have a [`DefaultAdapter`](http://godoc.org/github.com/doug-martin/goqu/#DefaultAdapter) that can be used as a base for any new Dialect specific adapter.
In fact for most use cases you will not have to override any methods but instead just override the default values as documented for [`DefaultAdapter`](http://godoc.org/github.com/doug-martin/goqu/#DefaultAdapter).


When creating your adapters you must register your adapter with [`RegisterAdapter`](http://godoc.org/github.com/doug-martin/goqu/#RegisterAdapter). This method requires 2 arguments.

1. Dialect - The dialect for your adapter.
2. DatasetAdapterFactory - This is a factory function that will return a new goqu.Adapter used to create the the dialect specific SQL.
1. dialect - The dialect for your adapter.
2. datasetAdapterFactory - This is a factory function that will return a new goqu.Adapter used to create the the dialect specific SQL.

Between most dialects there is a large portion of shared syntax, for this reason we have a DefaultAdapter that can be used as a base for any new Dialect specific adapter.
In fact for most use cases you will not have to override any methods but instead just override the default values as documented for DefaultAdapter.

For example the code for the postgres adapter is fairly short.
```go
Expand Down Expand Up @@ -591,8 +616,9 @@ func init() {
}
```

If you are looking to write your own adapter take a look at the postgres/mysql or sqlite3 adapter located at https://github.com/doug-martin/goqu/tree/master/adapters.
If you are looking to write your own adapter take a look at the postgresm, mysql or sqlite3 adapter located at <https://github.com/doug-martin/goqu/tree/master/adapters>.

<a name="contributions"></a>
## Contributions

I am always welcoming contributions of any type. Please open an issue or create a PR if you find an issue with any of the following.
Expand Down
4 changes: 2 additions & 2 deletions crud_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (me CrudExec) scan(i interface{}, query string, args ...interface{}) (bool,
}
}
if err := rows.Scan(scans...); err != nil {
return false, NewGoquError(err.Error())
return false, err
}
result := Record{}
for index, col := range columns {
Expand All @@ -207,7 +207,7 @@ func (me CrudExec) scan(i interface{}, query string, args ...interface{}) (bool,
results = append(results, result)
}
if rows.Err() != nil {
return false, NewGoquError(rows.Err().Error())
return false, rows.Err()
}
if len(results) > 0 {
found = true
Expand Down
14 changes: 14 additions & 0 deletions dataset_select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ func (me *datasetTest) TestWhere() {
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT * FROM "test" WHERE (("a" = 'a') AND ("b" != 'b') AND ("c" > 'c') AND ("d" >= 'd') AND ("e" < 'e') AND ("f" <= 'f'))`)

b = ds1.Where(
I("a").Eq(From("test2").Select("id")),
)
sql, err = b.Sql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT * FROM "test" WHERE ("a" IN (SELECT "id" FROM "test2"))`)

b = ds1.Where(Ex{
"a": "a",
"b": Op{"neq": "b"},
Expand All @@ -206,6 +213,13 @@ func (me *datasetTest) TestWhere() {
sql, err = b.Sql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT * FROM "test" WHERE (("a" = 'a') AND ("b" != 'b') AND ("c" > 'c') AND ("d" >= 'd') AND ("e" < 'e') AND ("f" <= 'f'))`)

b = ds1.Where(Ex{
"a": From("test2").Select("id"),
})
sql, err = b.Sql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT * FROM "test" WHERE ("a" IN (SELECT "id" FROM "test2"))`)
}

func (me *datasetTest) TestClearWhere() {
Expand Down
9 changes: 7 additions & 2 deletions dataset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package goqu
import (
"database/sql/driver"
"fmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"regexp"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

type datasetTest struct {
Expand Down Expand Up @@ -373,6 +374,8 @@ func (me *datasetTest) TestBooleanExpression() {
assert.Equal(t, buf.String(), `("a" IS NULL)`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Eq([]int64{1, 2, 3})))
assert.Equal(t, buf.String(), `("a" IN (1, 2, 3))`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Eq(From("test2").Select("id"))))
assert.Equal(t, buf.String(), `("a" IN (SELECT "id" FROM "test2"))`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Neq(1)))
assert.Equal(t, buf.String(), `("a" != 1)`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Neq(true)))
Expand All @@ -383,6 +386,8 @@ func (me *datasetTest) TestBooleanExpression() {
assert.Equal(t, buf.String(), `("a" IS NOT NULL)`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Neq([]int64{1, 2, 3})))
assert.Equal(t, buf.String(), `("a" NOT IN (1, 2, 3))`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Neq(From("test2").Select("id"))))
assert.Equal(t, buf.String(), `("a" NOT IN (SELECT "id" FROM "test2"))`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Is(nil)))
assert.Equal(t, buf.String(), `("a" IS NULL)`)
assert.NoError(t, ds.Literal(me.Truncate(buf), I("a").Is(false)))
Expand Down
2 changes: 2 additions & 0 deletions expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,8 @@ func checkBoolExpType(op BooleanOperation, lhs Expression, rhs interface{}, inve
op = IN_OP
case reflect.Struct:
switch rhs.(type) {
case SqlExpression:
op = IN_OP
case *regexp.Regexp:
return checkLikeExp(LIKE_OP, lhs, rhs, invert)
}
Expand Down

0 comments on commit 421dbb3

Please sign in to comment.