Skip to content

Commit

Permalink
Merge with v3
Browse files Browse the repository at this point in the history
  • Loading branch information
xiam committed May 2, 2017
2 parents a38072c + df86292 commit deacccd
Show file tree
Hide file tree
Showing 28 changed files with 1,756 additions and 14 deletions.
10 changes: 8 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
sudo: required
dist: precise

notifications:
email: false
Expand All @@ -9,9 +8,10 @@ language: go
go:
- "1.7"
- "1.8"
# - "tip"
# - "tip"

services:
- docker
- mongodb
- mysql
- postgresql
Expand All @@ -22,9 +22,15 @@ addons:
sources:
- mongodb-3.0-precise
packages:
- freetds-bin
- mongodb-org-server
- mongodb-org-shell

before_install:
- docker pull microsoft/mssql-server-linux:ctp1-4
- docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=my$Password' --name mssql -p 1433:1433 -d microsoft/mssql-server-linux:ctp1-4
- docker ps -a

env:
global:
- MAKEFLAGS="-j4"
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
SHELL := /bin/bash

WAPPER ?= all
DB_HOST ?= 127.0.0.1

export DB_HOST
export WRAPPER

benchmark-lib:
go test -v -benchtime=500ms -bench=. ./lib/...
Expand All @@ -20,12 +22,13 @@ test-internal:

test-libs: test-lib test-internal

test-adapters: test-adapter-postgresql test-adapter-mysql test-adapter-sqlite test-adapter-ql test-adapter-mongo
test-adapters: test-adapter-postgresql test-adapter-mysql test-adapter-sqlite test-adapter-mssql test-adapter-ql test-adapter-mongo

reset-db:
$(MAKE) -C postgresql reset-db && \
$(MAKE) -C mysql reset-db && \
$(MAKE) -C sqlite reset-db && \
$(MAKE) -C mssql reset-db && \
$(MAKE) -C ql reset-db && \
$(MAKE) -C mongo reset-db

Expand Down
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ Go that provides a common interface to work with different data sources such as
go get upper.io/db.v3
```

## User documentation
## The tour

This is the source code repository, check out our [release
notes](https://github.com/upper/db/releases/tag/v3.0.0) and see examples and
documentation at [upper.io/db.v3][1].
![screen shot 2017-05-01 at 19 23 22](https://cloud.githubusercontent.com/assets/385670/25599675/b6fe9fea-2ea3-11e7-9f76-002931dfbbc1.png)

## Demo
Take the [tour](https://tour.upper.io) to see real live examples in your
browser.

## Live demos

You can run the following example on our [playground](https://demo.upper.io):

Expand Down Expand Up @@ -87,6 +88,13 @@ go run _examples/booktown-books/main.go
2016/08/10 08:42:48 "Practical PostgreSQL" (ID: 41472)
```

## Documentation for users

This is the source code repository, check out our [release
notes](https://github.com/upper/db/releases/tag/v3.0.0) and see examples and
documentation at [upper.io/db.v3][1].


## Changelog

See [CHANGELOG.md](https://github.com/upper/db/blob/master/CHANGELOG.md).
Expand Down
75 changes: 72 additions & 3 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,20 @@ import (
"gopkg.in/mgo.v2/bson"
"upper.io/db.v3"
"upper.io/db.v3/mongo"
"upper.io/db.v3/mssql"
"upper.io/db.v3/mysql"
"upper.io/db.v3/postgresql"
"upper.io/db.v3/ql"
"upper.io/db.v3/sqlite"
)

var wrappers = []string{
sqlite.Adapter,
mongo.Adapter,
mssql.Adapter,
mysql.Adapter,
postgresql.Adapter,
mongo.Adapter,
ql.Adapter,
sqlite.Adapter,
}

const (
Expand Down Expand Up @@ -103,6 +105,12 @@ func init() {
"timezone": "UTC",
},
},
`mssql`: &mssql.ConnectionURL{
Database: `upperio_tests`,
Host: host,
User: `upperio_tests`,
Password: `upperio_Secre3t`,
},
`ql`: &ql.ConnectionURL{
Database: `ql-test.db`,
},
Expand Down Expand Up @@ -252,6 +260,65 @@ var setupFn = map[string]func(driver interface{}) error{
}
return fmt.Errorf("Expecting *sql.DB got %T (%#v).", driver, driver)
},
`mssql`: func(driver interface{}) error {
if sqld, ok := driver.(*sql.DB); ok {
var err error

_, err = sqld.Exec(`DROP TABLE IF EXISTS [birthdays]`)
if err != nil {
return err
}
_, err = sqld.Exec(`CREATE TABLE [birthdays] (
id BIGINT PRIMARY KEY NOT NULL IDENTITY(1,1),
name NVARCHAR(50),
born DATETIME,
born_ut BIGINT
)`)
if err != nil {
return err
}

_, err = sqld.Exec(`DROP TABLE IF EXISTS [fibonacci]`)
if err != nil {
return err
}
_, err = sqld.Exec(`CREATE TABLE [fibonacci] (
id BIGINT PRIMARY KEY NOT NULL IDENTITY(1,1),
input BIGINT NOT NULL,
output BIGINT NOT NULL
)`)
if err != nil {
return err
}

_, err = sqld.Exec(`DROP TABLE IF EXISTS [is_even]`)
if err != nil {
return err
}
_, err = sqld.Exec(`CREATE TABLE [is_even] (
input BIGINT NOT NULL,
is_even TINYINT
)`)
if err != nil {
return err
}

_, err = sqld.Exec(`DROP TABLE IF EXISTS [CaSe_TesT]`)
if err != nil {
return err
}
_, err = sqld.Exec(`CREATE TABLE [CaSe_TesT] (
id BIGINT PRIMARY KEY NOT NULL IDENTITY(1,1),
case_test NVARCHAR(60)
)`)
if err != nil {
return err
}

return nil
}
return fmt.Errorf("Expecting *sql.DB got %T (%#v).", driver, driver)
},
`sqlite`: func(driver interface{}) error {
if sqld, ok := driver.(*sql.DB); ok {
var err error
Expand Down Expand Up @@ -635,7 +702,7 @@ func TestSimpleCRUD(t *testing.T) {
}

if reflect.DeepEqual(testItem, controlItem) == false {
t.Fatalf("Struct is different with wrapper %s.", wrapper)
t.Fatalf("Struct is different with wrapper %s, got: %#v, expecting: %#v.", wrapper, testItem, controlItem)
}

err = res.Delete()
Expand Down Expand Up @@ -716,6 +783,8 @@ func TestFibonacci(t *testing.T) {
res = res.OrderBy(db.Raw(`RANDOM()`))
case `mysql`:
res = res.OrderBy(db.Raw(`RAND()`))
case `sqlserver`:
res = res.OrderBy(db.Raw(`NEWID()`))
}

total, err = res.Count()
Expand Down
29 changes: 29 additions & 0 deletions internal/sqladapter/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,35 @@ func (d *database) Collection(name string) db.Collection {
return col
}

// StatementPrepare creates a prepared statement.
func (d *database) StatementPrepare(ctx context.Context, stmt *exql.Statement) (sqlStmt *sql.Stmt, err error) {
var query string

if d.Settings.LoggingEnabled() {
defer func(start time.Time) {
d.Logger().Log(&db.QueryStatus{
TxID: d.txID,
SessID: d.sessID,
Query: query,
Err: err,
Start: start,
End: time.Now(),
})
}(time.Now())
}

tx := d.Transaction()

query, _ = d.compileStatement(stmt, nil)
if tx != nil {
sqlStmt, err = compat.PrepareContext(tx.(*baseTx), ctx, query)
return
}

sqlStmt, err = compat.PrepareContext(d.sess, ctx, query)
return
}

// StatementExec compiles and executes a statement that does not return any
// rows.
func (d *database) StatementExec(ctx context.Context, stmt *exql.Statement, args ...interface{}) (res sql.Result, err error) {
Expand Down
3 changes: 3 additions & 0 deletions internal/sqladapter/exql/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ func (c *Column) Compile(layout *Template) (compiled string, err error) {

for i := range nameChunks {
nameChunks[i] = trimString(nameChunks[i])
if nameChunks[i] == "*" {
continue
}
nameChunks[i] = mustParse(layout.IdentifierQuote, Raw{Value: nameChunks[i]})
}

Expand Down
22 changes: 22 additions & 0 deletions internal/sqladapter/exql/statement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,28 @@ func TestSelectStarFromMany(t *testing.T) {
}
}

func TestSelectTableStarFromMany(t *testing.T) {
var s, e string
var stmt Statement

stmt = Statement{
Type: Select,
Columns: JoinColumns(
&Column{Name: "foo.name"},
&Column{Name: "BAR.*"},
&Column{Name: "baz.last_name"},
),
Table: TableWithName("first.table AS foo, second.table as BAR, third.table aS baz"),
}

s = mustTrim(stmt.Compile(defaultTemplate))
e = `SELECT "foo"."name", "BAR".*, "baz"."last_name" FROM "first"."table" AS "foo", "second"."table" AS "BAR", "third"."table" AS "baz"`

if s != e {
t.Fatalf("Got: %s, Expecting: %s", s, e)
}
}

func TestSelectArtistNameFrom(t *testing.T) {
var s, e string
var stmt Statement
Expand Down
3 changes: 1 addition & 2 deletions internal/sqladapter/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,7 @@ func (r *Result) buildCount() (sqlbuilder.Selector, error) {

sel := r.SQLBuilder().Select(db.Raw("count(1) AS _t")).
From(res.table).
GroupBy(res.groupBy...).
Limit(1)
GroupBy(res.groupBy...)

for i := range res.conds {
sel = sel.And(filter(res.conds[i])...)
Expand Down
4 changes: 3 additions & 1 deletion internal/sqladapter/testing/adapter.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,6 @@ func TestTransactionsAndRollback(t *testing.T) {
err = artist.Truncate()
assert.NoError(t, err)
// Simple transaction
_, err = artist.Insert(artistType{1, "First"})
assert.NoError(t, err)
Expand Down Expand Up @@ -1263,9 +1262,12 @@ func TestDataTypes(t *testing.T) {
testValues := testValuesStruct{
1, 1, 1, 1, 1,
-1, -1, -1, -1, -1,
1.337, 1.337,
true,
"Hello world!",
ts,
nil,
&tnz,
Expand Down
28 changes: 28 additions & 0 deletions lib/sqlbuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ var (
)

type exprDB interface {
StatementPrepare(ctx context.Context, stmt *exql.Statement) (*sql.Stmt, error)
StatementQuery(ctx context.Context, stmt *exql.Statement, args ...interface{}) (*sql.Rows, error)
StatementQueryRow(ctx context.Context, stmt *exql.Statement, args ...interface{}) (*sql.Row, error)
StatementExec(ctx context.Context, stmt *exql.Statement, args ...interface{}) (sql.Result, error)
Expand Down Expand Up @@ -132,6 +133,23 @@ func (b *sqlBuilder) IteratorContext(ctx context.Context, query interface{}, arg
return &iterator{rows, err}
}

func (b *sqlBuilder) Prepare(query interface{}) (*sql.Stmt, error) {
return b.PrepareContext(b.sess.Context(), query)
}

func (b *sqlBuilder) PrepareContext(ctx context.Context, query interface{}) (*sql.Stmt, error) {
switch q := query.(type) {
case *exql.Statement:
return b.sess.StatementPrepare(ctx, q)
case string:
return b.sess.StatementPrepare(ctx, exql.RawSQL(q))
case db.RawValue:
return b.PrepareContext(ctx, q.Raw())
default:
return nil, fmt.Errorf("Unsupported query type %T.", query)
}
}

func (b *sqlBuilder) Exec(query interface{}, args ...interface{}) (sql.Result, error) {
return b.ExecContext(b.sess.Context(), query, args...)
}
Expand Down Expand Up @@ -389,6 +407,8 @@ func columnFragments(columns []interface{}) ([]exql.Fragment, []interface{}, err
f[i] = v
case string:
f[i] = exql.ColumnWithName(v)
case int:
f[i] = exql.RawValue(fmt.Sprintf("%v", v))
case interface{}:
f[i] = exql.ColumnWithName(fmt.Sprintf("%v", v))
default:
Expand Down Expand Up @@ -562,6 +582,14 @@ func (p *exprProxy) StatementExec(ctx context.Context, stmt *exql.Statement, arg
return compat.ExecContext(p.db, ctx, s, args)
}

func (p *exprProxy) StatementPrepare(ctx context.Context, stmt *exql.Statement) (*sql.Stmt, error) {
s, err := stmt.Compile(p.t)
if err != nil {
return nil, err
}
return compat.PrepareContext(p.db, ctx, s)
}

func (p *exprProxy) StatementQuery(ctx context.Context, stmt *exql.Statement, args ...interface{}) (*sql.Rows, error) {
s, err := stmt.Compile(p.t)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions lib/sqlbuilder/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ func (del *deleter) Arguments() []interface{} {
return dq.arguments()
}

func (del *deleter) Prepare() (*sql.Stmt, error) {
return del.PrepareContext(del.SQLBuilder().sess.Context())
}

func (del *deleter) PrepareContext(ctx context.Context) (*sql.Stmt, error) {
dq, err := del.build()
if err != nil {
return nil, err
}
return del.SQLBuilder().sess.StatementPrepare(ctx, dq.statement())
}

func (del *deleter) Exec() (sql.Result, error) {
return del.ExecContext(del.SQLBuilder().sess.Context())
}
Expand Down
Loading

0 comments on commit deacccd

Please sign in to comment.