diff --git a/HISTORY.md b/HISTORY.md
index 586ac6cf..e1c20bd0 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -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)
diff --git a/README.md b/README.md
index 22c7e355..3a8cfee5 100644
--- a/README.md
+++ b/README.md
@@ -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
@@ -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)
+
## Basics
In order to start using goqu with your database you need to load an adapter. We have included some adapters by default.
@@ -84,6 +100,7 @@ SELECT * FROM "user" WHERE "id" = 10
SELECT * FROM "user" WHERE "id" = $1
```
+
### 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.
@@ -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)
```
-
+
### Complex Example
Using the Ex map syntax
@@ -319,10 +336,12 @@ HAVING (AVG("test3"."age") > 10)
ORDER BY "test"."created" DESC NULLS LAST
```
-### Querying
+
+## Querying
goqu also has basic query support through the use of either the Database or the Dataset.
+
### Dataset
* [`ScanStructs`](http://godoc.org/github.com/doug-martin/goqu#Dataset.ScanStructs) - scans rows into a slice of structs
@@ -474,6 +493,7 @@ if err := delete.ScanVals(&ids); err != nil{
}
```
+
### Database
The Database also allows you to execute queries but expects raw SQL to execute. The supported methods are
@@ -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
+
+### Transactions
`goqu` has builtin support for transactions to make the use of the Datasets and querying seamless
@@ -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`
@@ -543,6 +564,7 @@ if err != nil{
}
```
+
## 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.
@@ -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
+
## 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
@@ -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 .
+
## 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.
diff --git a/crud_exec.go b/crud_exec.go
index 008635a8..2b4aaac7 100644
--- a/crud_exec.go
+++ b/crud_exec.go
@@ -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 {
@@ -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
diff --git a/dataset_select_test.go b/dataset_select_test.go
index 642e36e6..8ef156af 100644
--- a/dataset_select_test.go
+++ b/dataset_select_test.go
@@ -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"},
@@ -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() {
diff --git a/dataset_test.go b/dataset_test.go
index b79c2701..525003ed 100644
--- a/dataset_test.go
+++ b/dataset_test.go
@@ -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 {
@@ -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)))
@@ -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)))
diff --git a/expressions.go b/expressions.go
index b2421bc9..cd20e635 100644
--- a/expressions.go
+++ b/expressions.go
@@ -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)
}