Coder Social home page Coder Social logo

jet's People

Contributors

hebo avatar pzduniak avatar tcolar 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  avatar  avatar  avatar

jet's Issues

Question : Importing PG driver

Is this not necessary when working with Postgres

import "github.com/lib/pq"

This code below works: what driver is being used?

package db

import (
    "fmt"

    "github.com/eaigner/jet"
    //_ "github.com/lib/pq"
)
func OpenPg() *jet.Db {
    db, err := jet.Open("postgres", "dbname=mobifit_dev user=postgres password=password host=localhost sslmode=disable")

    if err != nil {
        panic(err)
    }

    if err := db.Ping(); err != nil {
        panic(err)
    }

    db.LogFunc = func(queryId, query string, args ...interface{}) {
        fmt.Printf("JET: %s ARG: %v\n", query, args)
    }

    return db
}

// Elsewhere
db := OpenPg()
    var amount int
    db.Query("SELECT 2").Rows(&amount)
    fmt.Println(amount) // = 2

Prepared statements are never deallocated

jet/query.go

Line 72 in ae59b2c

stmt, err = q.qo.Prepare(query)

In the case of a transaction, jet always creates a prepared statement but never deallocate them. It looks like postgres automatically clears prepared statement when the session is reset, MySQL doesn't. When using this feature for too long, MySQL quickly reaches the max amount of created statements.

I'm not quite sure what the right behavior should be but deallocation should at least be doable by the users (currently the statement isn't exposed).

the newQueryId in utils.go are not thread safe

becaues the gen.Intn are not thread safe

package main

import (
    "math/rand"
    "runtime"
    "sync"
    "time"
)
var (
    gen = rand.New(rand.NewSource(time.Now().UnixNano()))
)

func main() {
    runtime.GOMAXPROCS(2)
    g := sync.WaitGroup{}
    for i := 0; i < 2; i++ {
        g.Add(1)
        go func() {
            _ = gen.Int()
            g.Done()
        }()
    }
    g.Wait()
}

WARNING: DATA RACE
Write by goroutine 5:
math/rand.(_rngSource).Int63()
/usr/local/go/src/pkg/math/rand/rng.go:233 +0x3a
math/rand.(_Rand).Int63()
/usr/local/go/src/pkg/math/rand/rand.go:37 +0x48
math/rand.(*Rand).Int()
/usr/local/go/src/pkg/math/rand/rand.go:47 +0x32
main.func·001()
/project/works/open/src/example/main.go:45 +0x4f
gosched0()
/usr/local/go/src/pkg/runtime/proc.c:1218 +0x9f

Previous write by goroutine 4:
math/rand.(_rngSource).Int63()
/usr/local/go/src/pkg/math/rand/rng.go:233 +0x3a
math/rand.(_Rand).Int63()
/usr/local/go/src/pkg/math/rand/rand.go:37 +0x48
math/rand.(*Rand).Int()
/usr/local/go/src/pkg/math/rand/rand.go:47 +0x32
main.func·001()
/project/works/open/src/example/main.go:45 +0x4f
gosched0()
/usr/local/go/src/pkg/runtime/proc.c:1218 +0x9f

Goroutine 5 (running) created at:
main.main()
/project/works/open/src/example/main.go:47 +0x145
runtime.main()
/usr/local/go/src/pkg/runtime/proc.c:182 +0x91

Goroutine 4 (finished) created at:
main.main()
/project/works/open/src/example/main.go:47 +0x145
runtime.main()
/usr/local/go/src/pkg/runtime/proc.c:182 +0x91

pq repo moved

It is now: github.com/lib/pq

db_test.go:4:   _ "github.com/bmizerany/pq"
tx_test.go:4:   _ "github.com/bmizerany/pq"

weird error probably due to caching

I see seldom errors like this one:

sql: expected 12 arguments, got 1

When logging the query that triggered the error, I can see that the query is actually the wrong one:

Query: &jet.runner{db:(*sql.DB)(0xc2000d02a0), tx:(*sql.Tx)(nil), stmt:(*sql.Stmt)(0xc20165d600), qo:(*sql.DB)(0xc2000d02a0), conv:(*jet.snakeConv)(0x8e0a88), expand:false, txnId:"", query:"select * from users WHERE authentication_token = ? limit 1", lastErr:error(nil), args:[]interface {}{"XXXXXX"}, logger:(*jet.Logger)(nil), lru:(*jet.lruCache)(0xc2000c1820)}

So for some reason, Jet gets confused and uses the wrong statement which then fails since the passed arguments don't match.

Any idea what's going on?

Is there no support for floats?

Couldn't successfully query a table containing columns of type decimal. I thought I was doing something wrong, but looking through the tests and source leaves me doubting whether there is support at all.

Multiple Result Sets

Does Jet have support for returning multiple result sets?
E.g in one query select * from x; select * from y, and then you iterate through the results. This would be useful for eager loading.

Expose LastInsertId()/RowsAffected()

As far as I can see there is no way of getting this from a result. I see in your tests you use some PostgreSQL specific queries to work around the issue.

Panic in q.stmt.Close() is preventing the "root" error to be passed through

Often if I have a bad SQL query and the mapping failsI don't get the root error, because instead I get a Panic from the q.stmt.close() (query.go:36)

A simple fix was to either prevent the panic q.stmt.close() or this seem to work too:
if q.db.LRUCache == nil && q.stmt != nil {
q.stmt.Close()
}

Otherwise I would always get a panic like such when Rows() mapping failed:

Running: [go, test]
warning: building out-of-date packages:
github.com/eaigner/jet
github.com/tcolar/phpserializer
installing these packages with 'go test -i' will speed future tests.

2013/09/12 14:10:22 drupsway_test.go:27: Test Start
--- FAIL: TestProducts (0.00 seconds)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x28 pc=0x4b883d]

goroutine 4 [running]:
testing.func·004()
/usr/local/go/src/pkg/testing/testing.go:348 +0xcd
sync/atomic.CompareAndSwapUint32()
/usr/local/go/src/pkg/sync/atomic/asm_amd64.s:14 +0xd
sync.(_Mutex).Lock(0x28)
/usr/local/go/src/pkg/sync/mutex.go:43 +0x35
sync.(_RWMutex).Lock(0x28)
/usr/local/go/src/pkg/sync/rwmutex.go:78 +0x25
database/sql.(_Stmt).Close(0x0, 0x0, 0x0)
/usr/local/go/src/pkg/database/sql/sql.go:1241 +0x3c
github.com/eaigner/jet.func·001()
/home/tcolar/DEV/go/src/github.com/eaigner/jet/query.go:36 +0x4c
github.com/eaigner/jet.(_query).Rows(0xc20016bc40, 0x6bf840, 0xc20012a960, 0x0, 0x0, ...)
/home/tcolar/DEV/go/src/github.com/eaigner/jet/query.go:42 +0xb9

......

goroutine 2 [syscall]:
exit status 2
FAIL 0.034s


MySQL support?

Hi, just curious if this is supposed to work with MySQL?

I tried to use it like this:

Jet, err = jet.Open("mysql", spec)
rowNum := 500 
var w World 
Jet.Query(worldSelect, rowNum).Value(&w)

For the query, I tried these:

const worldSelect = "SELECT id,randomNumber FROM World where id = ?"
const worldSelect = "SELECT id,randomNumber FROM World where id = $1"
const worldSelect = "SELECT id,randomNumber FROM World where id = "

but all failed, with these various error messages:

SQL: 2013/05/08 00:12:46 SELECT id,randomNumber FROM World where id = $1 ["8082"]
Error scanning world row: Error 1054: Unknown column '$1' in 'where clause'

SQL: 2013/05/08 00:13:04 SELECT id,randomNumber FROM World where id = ? ["8082"]
Error scanning world row: Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?$1' at line 1

SQL: 2013/05/08 00:13:20 SELECT id,randomNumber FROM World where id =  ["8082"]
Error scanning world row: Error 1054: Unknown column '$1' in 'where clause'

Query generator adds an additional parameter

My PostgreSQL table is:

CREATE TABLE users (
    id        serial primary key,
    username  varchar(64),
    password  varchar(128),
    email     varchar(64),
    firstname varchar(64), 
    lastname  varchar(128),
    activated boolean
);

Unfortunately, the following code returns 2014/01/03 17:28:05 Query failed; pq: syntax error at or near "$6"

db, err := jet.Open("postgres", cfg.Database.ConnectionString)
if err != nil {
    log.Fatalf("Error while connecting to the database; %s", err)
}

err = db.Query(`
    INSERT INTO "users" (
        "username",
        "password",
        "email",
        "firstname",
        "activated"
    )
    VALUES (
        $1,
        $2,
        $3,
        $4,
        $5
    )`,
    "admin",
    utils.HashPassword(admin),
    "[email protected]",
    "John",
    "Doe",
    true
).Run()
if err != nil {
    log.Fatalf("Query failed; %s", err)
}

Am I doing something wrong or is it an issue with the latest version of jet?

support for time.Time unmapping

I tried to look at Hood and how I could add this feature but I got stuck in mapper.go land.

I'm not quite sure how to unmap a timestamp value coming from MySql into a time.Time value. This MySql driver seems to be doing the conversion for you (optionally) https://github.com/go-sql-driver/mysql#timetime-support but I didn't manage a way to get the unmapping to work if the data comes as a byte array or another type.

As far as I can tell, the challenge is that unpackStruct tries to handle the timestamp value and we end up with a blank time value,

func (m *mapper) unpackStruct(keys []string, values []interface{}, out reflect.Value) error

I really wish I could help, but I'm stuck :(

Cannot convert time.Time to pq.NullTime

I have a model like this:

type User struct {
    Id             int
    Email          string
    HashedPassword []byte
    CreatedAt      time.Time
    ConfirmedAt    pq.NullTime
}

and if I write some code to fetch a value from the database where the time has already been set:

func (u *User) GetByEmail(email string) error {
    pg := db.OpenPg()
    defer pg.Close()

    err := pg.Query("SELECT * FROM _users__get_by_email($1);",
        email).
        Rows(u)

    fmt.Println(u)

    if u.Id == 0 {
        err = db.EntityNotFound
    }

    return err
}

I get this error below:

[martini] PANIC: reflect.Value.Convert: value of type time.Time cannot be converted to type pq.NullTime
/home/lee/Code/gocode/src/github.com/codegangsta/martini/recovery.go:48 (0x468046)
    com/codegangsta/martini.func.003: log.Printf("PANIC: %s\n%s", err, debug.Stack())
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/panic.c:248 (0x414ee6)
    panic: runtime·newstackcall(d->fn, (byte*)d->args, d->siz);
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:2210 (0x55454f)
    Value.Convert: panic("reflect.Value.Convert: value of type " + v.typ.String() + " cannot be converted to type " + t.String())
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:119 (0x59a6af)
    com/eaigner/jet.convertAndSet: to.Set(from.Convert(to.Type()))
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:202 (0x59bb7a)
    com/eaigner/jet.setValueFromTime: convertAndSet(t, to)
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:136 (0x59abcd)
    com/eaigner/jet.setValue: setValueFromTime(t, to)
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:112 (0x59a5b1)
    com/eaigner/jet.(*mapper).unpackSimple: setValue(reflect.Indirect(reflect.ValueOf(values[0])), out)
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:75 (0x599e05)
    com/eaigner/jet.(*mapper).unpackStruct: return m.unpackSimple(nil, values, out)
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:51 (0x599ace)
    com/eaigner/jet.(*mapper).unpackValue: return m.unpackStruct(keys, values, out)
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:86 (0x59a039)
    com/eaigner/jet.(*mapper).unpackStruct: m.unpackValue(nil, values[i:i+1], field)
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:51 (0x599ace)
    com/eaigner/jet.(*mapper).unpackValue: return m.unpackStruct(keys, values, out)
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:43 (0x599956)
    com/eaigner/jet.(*mapper).unpackValue: return m.unpackValue(keys, values, reflect.Indirect(out))
/home/lee/Code/gocode/src/github.com/eaigner/jet/mapper.go:20 (0x599246)
    com/eaigner/jet.(*mapper).unpack: return m.unpackValue(keys, values, val)
/home/lee/Code/gocode/src/github.com/eaigner/jet/query.go:118 (0x59c581)
    com/eaigner/jet.(*jetQuery).Rows: err = colMapper.unpack(cols, cont, v)
/home/lee/Code/gocode/src/mobifit/app/models/user.go:130 (0x4292fd)
    (*User).GetByEmail: Rows(u)
/home/lee/Code/gocode/src/mobifit/app/controllers/page_controller.go:12 (0x427d73)
    PageContact: err := u.GetByEmail("[email protected]")
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/asm_amd64.s:338 (0x425922)
    call16: CALLFN(call16, 16)
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:474 (0x54e2eb)
    Value.call: call(fn, ptr, uint32(size))
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:345 (0x54d3dd)
    Value.Call: return v.call("Call", in)
/home/lee/Code/gocode/src/github.com/codegangsta/inject/inject.go:98 (0x546214)
    com/codegangsta/inject.(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
/home/lee/Code/gocode/src/github.com/codegangsta/martini/env.go:1 (0x46991c)
    com/codegangsta/martini.(*context).Invoke: package martini
/home/lee/Code/gocode/src/github.com/codegangsta/martini/router.go:244 (0x467707)
    com/codegangsta/martini.(*routeContext).run: vals, err := r.Invoke(handler)
/home/lee/Code/gocode/src/github.com/codegangsta/martini/router.go:178 (0x467164)
    com/codegangsta/martini.(*route).Handle: context.run()
/home/lee/Code/gocode/src/github.com/codegangsta/martini/router.go:91 (0x46863e)
    com/codegangsta/martini.*route.Handle.fm: _, err := context.Invoke(route.Handle)
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/asm_amd64.s:339 (0x425982)
    call32: CALLFN(call32, 32)
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:474 (0x54e2eb)
    Value.call: call(fn, ptr, uint32(size))
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:345 (0x54d3dd)
    Value.Call: return v.call("Call", in)
/home/lee/Code/gocode/src/github.com/codegangsta/inject/inject.go:98 (0x546214)
    com/codegangsta/inject.(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
/home/lee/Code/gocode/src/github.com/codegangsta/martini/env.go:1 (0x46991c)
    com/codegangsta/martini.(*context).Invoke: package martini
/home/lee/Code/gocode/src/github.com/codegangsta/martini/router.go:91 (0x466689)
    com/codegangsta/martini.(*router).Handle: _, err := context.Invoke(route.Handle)
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:104 (0x467fb0)
    com/codegangsta/martini.Router.Handle.fm: m.Action(r.Handle)
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/asm_amd64.s:340 (0x4259e2)
    call64: CALLFN(call64, 64)
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:474 (0x54e2eb)
    Value.call: call(fn, ptr, uint32(size))
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:345 (0x54d3dd)
    Value.Call: return v.call("Call", in)
/home/lee/Code/gocode/src/github.com/codegangsta/inject/inject.go:98 (0x546214)
    com/codegangsta/inject.(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:147 (0x465748)
    com/codegangsta/martini.(*context).run: _, err := c.Invoke(c.handlers[c.index])
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:138 (0x46568b)
    com/codegangsta/martini.(*context).Next: c.run()
/home/lee/Code/gocode/src/github.com/martini-contrib/sessions/sessions.go:93 (0x470af4)
    com/martini-contrib/sessions.func.002: c.Next()
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/asm_amd64.s:340 (0x4259e2)
    call64: CALLFN(call64, 64)
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:474 (0x54e2eb)
    Value.call: call(fn, ptr, uint32(size))
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:345 (0x54d3dd)
    Value.Call: return v.call("Call", in)
/home/lee/Code/gocode/src/github.com/codegangsta/inject/inject.go:98 (0x546214)
    com/codegangsta/inject.(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:147 (0x465748)
    com/codegangsta/martini.(*context).run: _, err := c.Invoke(c.handlers[c.index])
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:138 (0x46568b)
    com/codegangsta/martini.(*context).Next: c.run()
/home/lee/Code/gocode/src/github.com/codegangsta/martini/recovery.go:57 (0x468366)
    com/codegangsta/martini.func.004: c.Next()
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/asm_amd64.s:340 (0x4259e2)
    call64: CALLFN(call64, 64)
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:474 (0x54e2eb)
    Value.call: call(fn, ptr, uint32(size))
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:345 (0x54d3dd)
    Value.Call: return v.call("Call", in)
/home/lee/Code/gocode/src/github.com/codegangsta/inject/inject.go:98 (0x546214)
    com/codegangsta/inject.(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:147 (0x465748)
    com/codegangsta/martini.(*context).run: _, err := c.Invoke(c.handlers[c.index])
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:138 (0x46568b)
    com/codegangsta/martini.(*context).Next: c.run()
/home/lee/Code/gocode/src/github.com/codegangsta/martini/logger.go:16 (0x467d78)
    com/codegangsta/martini.func.001: c.Next()
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/asm_amd64.s:340 (0x4259e2)
    call64: CALLFN(call64, 64)
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:474 (0x54e2eb)
    Value.call: call(fn, ptr, uint32(size))
/home/lee/.gvm/gos/go1.2/src/pkg/reflect/value.go:345 (0x54d3dd)
    Value.Call: return v.call("Call", in)
/home/lee/Code/gocode/src/github.com/codegangsta/inject/inject.go:98 (0x546214)
    com/codegangsta/inject.(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:147 (0x465748)
    com/codegangsta/martini.(*context).run: _, err := c.Invoke(c.handlers[c.index])
/home/lee/Code/gocode/src/github.com/codegangsta/martini/martini.go:68 (0x464c73)
    com/codegangsta/martini.(*Martini).ServeHTTP: m.createContext(res, req).run()
/home/lee/.gvm/gos/go1.2/src/pkg/net/http/server.go:1597 (0x43d4fe)
    serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/home/lee/.gvm/gos/go1.2/src/pkg/net/http/server.go:1167 (0x43b507)
    (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/home/lee/.gvm/gos/go1.2/src/pkg/runtime/proc.c:1394 (0x4191e0)
    goexit: runtime·goexit(void)
[martini] Completed 500 Internal Server Error in 136.896358ms

Expose a query an interface to handle reconnections on error

Due to a bug in Go https://code.google.com/p/go/issues/detail?id=5718 autoreconnection doesn't work with prepared statements. It sometimes leads to issues and bad connections. I would be nice if Jet could expose an interface to handle errors and let the developers reconnect and retry the query.

I noticed this method, but it's not currently exported so I can't hook into it.
https://github.com/eaigner/jet/blob/master/query.go#L132

Thanks

Question: pq - error has no field or method Code

I must be missing something simple here! Can someone point it out to me?

err := DB.Query(`INSERT INTO "users" ( "email" ) VALUES ( $1 )`, "[email protected]").Run()
fmt.Println(err)
typ := reflect.TypeOf(err)
fmt.Println(typ)

if typ.Kind() == reflect.Ptr {
        typ = typ.Elem()
}
for i := 0; i < typ.NumField(); i++ {
        p := typ.Field(i)
        if !p.Anonymous {
                fmt.Println(p.Name, "--", p.Type)
        }
}

Yields, as expected:

pq: duplicate key value violates unique constraint "unique_email"
*pq.Error
Severity -- string
Code -- pq.ErrorCode
Message -- string
Detail -- string
Hint -- string
Position -- string
InternalPosition -- string
InternalQuery -- string
Where -- string
Schema -- string
Table -- string
Column -- string
DataTypeName -- string
Constraint -- string
File -- string
Line -- string
Routine -- string

But if I add:

fmt.Println(err.Code)

I get this when I build:

err.Code undefined (type error has no field or method Code)

Much thanks!

issue with new complex value encode/decode interface

Here is my implementation of a MySQL time encoder/decoder: https://gist.github.com/mattetti/6692464

I'm having an issue where I have a User type like this:

type User struct {
    Id                  int
    Name                string
    Email               string
    CreatedAt           DbTime
}

When I save the record, everything works fine, the encoder seems to work. But when I retrieve the row, the decoder reports properly decoding the object (from the output) but the user object itself has a zeroed CreatedAt value.

I'm very confused and I'm not sure if that's an issue due to the way I use the interface, or an actual bug.

My test is very simple:

func TestUserDbTime(t *testing.T) {
  var user User
  u := User{Name: "matt", CreatedAt: DbTime{String:"2013-07-17 06:08:04 +0000 UTC"}}
  u.Create()
    err := Db.Query(`select * from users limit 1`).Rows(&user)
  assert.Nil(t, err)
  t.Logf("user: %#v", user)
  assert.False(t, user.CreatedAt.IsZero())
}

Whatever I do, the user.CreatedAt value is zeroed. What am I missing?

Struct in structs with joins?

In the following example, I would like the User field of the Post struct to be filled in with the user data from the query. Is such a thing possible? Currently, I am running two select statements. First getting the post and then getting the user.

type User struct {
    Id       int64
    Username string
}

type Post struct {
    Id   int64
    Text string
    User *User
}

func GetPost(id int64) {
    var post Post
    db.Query(`SELECT * FROM "post" LEFT JOIN "user" ON user.id = post.user_id`).Rows(&post)
}

problems mapping boolean values

Using MySQL I wasn't able to map a tinyint to a go boolean type.

I would like to be able to do that:

type Project struct {
    Id          int
    Name     string
    Public     bool
    Active     bool
}

var project Project
_ := Db.Query(`select * from projects WHERE id = ? limit 1`, id).Rows(&project)

undefined: sha1.Sum

➜ ~ go version
go version go1.1.2 linux/amd64

➜ ~ go get github.com/eaigner/jet

github.com/eaigner/jet

gopath/src/github.com/eaigner/jet/lru.go:84: undefined: sha1.Sum

Deadlock when doing a query that returns no data (update)

Since yesterday I've been fighting a serious issue since updating to the latest jet (using go 1.2 amd64).

Symptom is that when I do any kind of "update" query, that query "deadlocks" and never returns.

After much debugging I found the following:
In jet query.Rows() the defer that contains "q.m.Unlock()" was not being called.
Took a while to find why, it turns out another defer, the one for "rows.Close()" is hanging.

I'm still not getting why rows.Close() is hanging however, i was thinking that maybe it was nil and casing a panic but that doesn't seem to be the case.

If I take out the "defer rows.Close()" then all works properly although I would think that's probably not the right thing to do.

I haven't found yet what might be causing rows.close to hang however .... any ideas ?

License?

Jet does not include a LICENSE file. Can you clarify which license Jet is licensed under?

Feature request: NextRow

This is a great lightweight framework, but I wish it had the ability to read one row at a time. I have some larger queries that I can't afford to pull completely into memory. Maybe something like a callback where a false return means "I'm done fetching rows now"?

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.