mgutz / dat Goto Github PK
View Code? Open in Web Editor NEWGo Postgres Data Access Toolkit
License: Other
Go Postgres Data Access Toolkit
License: Other
I have implemented a custom type the worked fine with sqlx, but I cannot get it to work here.
The error i'm getting is
panic: Could not find struct tag in type PerformerEntity:
db:"aliases"`
The mapping
type PerformerEntity struct {
Id uint8 `json:"id"`
ExternalId uint8 `db:"external_id"json:"externalId"form:"uint8"`
OriginService string `db:"origin_service"json:"originService"`
OriginSection *string `db:"origin_section"json:"originSection"`
StageName string `db:"stage_name"json:"stageName"`
Aliases PGStringArray `json:"aliases"`
UpdatedAt time.Time `db:"updated_at"json:"updatedAt"`
CreatedAt time.Time `db:"created_at"json:"createdAt"`
}
When I include code like the following in an HTTP HandlerFunc (or its ilk), and an error occurs in the database layer (e.g. "pq: duplicate key value violates unique constraint "feeds_pkey""), the DB session doesn't close and dat panics after around 60s (killing the application):
tx, err := svc.DB.Begin()
if err != nil {
http.Error(out, err.Error(), http.StatusInternalServerError)
return
}
defer tx.AutoRollback()
// "feed" was unmarshaled from a JSON document...
if err := feed.Insert(tx); err != nil {
http.Error(out, err.Error(), http.StatusBadRequest)
return
}
if err := tx.Commit(); err != nil {
http.Error(out, err.Error(), http.StatusInternalServerError)
return
}
out.WriteHeader(http.StatusNoContent)
But if I move the transaction inside the functions, everything is fine when the error occurs (this doesn't panic):
// "DB" is a *dat.DB
if err := feed.Insert(DB); err != nil {
http.Error(out, err.Error(), http.StatusBadRequest)
return
}
out.WriteHeader(http.StatusNoContent)
Why isn't the "defer tx.AutoRollback()" firing and releasing the session when it's in an HTTP handler?
When performing an Update or Insert with Returning(*)
the error pq: column "*" does not exist
is thrown.
Hi, I have issue with
// EnableInterpolation = true
data := []interface{}{1,"hello", true} // some data
db.Exec("INSERT INTO table (a, b, c) VALUES ($1, $2, $3)", data)
=> err: sql: converting Exec argument #0's type: unsupported type []interface {}, a slice
using driver github.com/jackc/pgx/stdlib
, package gopkg.in/mgutz/dat.v2/dat
maybe someone was had this error, so can help me. Also it will be cool func .Values()
to can handle slice
It would be nice to have a ForUpdate function in the SelectBuilder for working with transactions and row-level locking.
Or is there another approach I'm missing?
Right now logxi is embedded inside dat and is not accessible or configurable, except through the command line. For applications that use alternate logging libraries or aren't 12-factor apps, this makes using dat problematic and often cumbersome. For example, I am apparently supposed to be able to redirect STDOUT to a log file if needs be, but nothing gets written when I do that. I fear if I can get it to work, the file will then fill with ANSI escape characters, making the log file unreadable. Furthermore, we would like to configure logging ourselves and use remote syslog, but this is impossible with dat, as logxi does not support this.
It would be far better if dat simply returned error messages, instead of performing its own logging.
If i am running a query like below, is sql injection possible?
var json []byte
json, _ = con.SQL(`SELECT id, user_name, created_at FROM users WHERE user_name = $1 `,
"mario",
).QueryJSON()
If yes, how to modify this query to prevent SQL injection?
Thanks for this package. It has saved me lot of boilerplate code.
Whenever I get a referential integrity error in dat (a FK violated) I get the following log:
SSSSSS19:57:49.958360 ERR dat:sqlx queryStruct.3
err: pq: insert or update on table "offers" violates foreign key constraint "offers_game_id_fkey"
sql: WITH upd AS ( UPDATE "offers" SET "game_id" = $1, "offer_template_id" = $2, "player_id" = $3 WHERE (id=$4) RETURNING "id","created_at","updated_at","claimed_at"), ins AS ( INSERT INTO "offers"("game_id","offer_template_id","player_id") SELECT $1,$2,$3 WHERE NOT EXISTS (SELECT 1 FROM upd) RETURNING "id","created_at","updated_at","claimed_at") SELECT * FROM ins UNION ALL SELECT * FROM upd
args: $1=invalid-game $2=e6683585-2fb6-4dd9-8069-f4014a16638e $3=player-3 $4=00000000-0000-0000-0000-000000000000
goroutine 22 [running]:
runtime/debug.Stack(0x10, 0xc42018cc20, 0xc0180)
/usr/local/Cellar/go/1.7.4_2/libexec/src/runtime/debug/stack.go:24 +0x79
github.com/topfreegames/offers/vendor/github.com/mgutz/logxi/v1.(*HappyDevFormatter).getLevelContext(0xc42008fc60, 0x3, 0xc420329a40, 0x0, 0x0, 0x0, 0x0, 0xc420078c78, 0x5)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/mgutz/dat/sqlx-runner/exec.go:77 +0x33c
github.com/topfreegames/offers/vendor/github.com/mgutz/dat/sqlx-runner.(*Execer).queryStructFn(0xc420366000, 0x489060, 0xc42033ad20, 0x0, 0x0)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/mgutz/dat/sqlx-runner/exec.go:395 +0x235
github.com/topfreegames/offers/vendor/github.com/mgutz/dat/sqlx-runner.(*Execer).queryStruct(0xc420366000, 0x489060, 0xc42033ad20, 0xc42033ae01, 0xc4203270c0)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/mgutz/dat/sqlx-runner/exec.go:355 +0x63
github.com/topfreegames/offers/vendor/github.com/mgutz/dat/sqlx-runner.(*Execer).QueryStruct(0xc420366000, 0x489060, 0xc42033ad20, 0x4, 0xc42033adc0)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/mgutz/dat/sqlx-runner/execer.go:133 +0x97
github.com/topfreegames/offers/models.UpsertOffer.func1(0x594979, 0x594978)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/models/offer.go:62 +0x267
github.com/topfreegames/offers/models.(*MixedMetricsReporter).WithDatastoreSegment(0x0, 0x54e514, 0x6, 0x54e8e6, 0x6, 0xc42018d4c8, 0x0, 0x0)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/models/mixed_metrics_reporter.go:40 +0x183
github.com/topfreegames/offers/models.UpsertOffer(0x7b3900, 0xc420332240, 0xc42033ad20, 0x0, 0xc42004f588, 0x2afe3)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/models/offer.go:63 +0xbc
github.com/topfreegames/offers/models_test.glob..func4.3.3()
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/models/offer_test.go:135 +0xd1
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/leafnodes.(*runner).runSync(0xc420258b40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go:104 +0x8d
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/leafnodes.(*runner).run(0xc420258b40, 0xc42004f7b0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go:63 +0xe1
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/leafnodes.(*ItNode).Run(0xc420290720, 0x7aa5c0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/leafnodes/it_node.go:25 +0x64
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/spec.(*Spec).runSample(0xc42009cfc0, 0x0, 0x7aa5c0, 0xc420142c90)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/spec/spec.go:167 +0x4fd
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/spec.(*Spec).Run(0xc42009cfc0, 0x7aa5c0, 0xc420142c90)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/spec/spec.go:118 +0xbe
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpecs(0xc42025b0e0, 0x597001)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:144 +0x262
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).Run(0xc42025b0e0, 0x19)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:61 +0xf0
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/suite.(*Suite).Run(0xc420073090, 0x96f828, 0xc42009ca80, 0x55aaf9, 0x19, 0xc4202f6040, 0x1, 0x1, 0x7b0980, 0xc420142c90, ...)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/internal/suite/suite.go:59 +0x23b
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo.RunSpecsWithCustomReporters(0x7ab300, 0xc42009ca80, 0x55aaf9, 0x19, 0xc42018df00, 0x1, 0x1, 0x0)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:207 +0x27b
github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo.RunSpecs(0x7ab300, 0xc42009ca80, 0x55aaf9, 0x19, 0xc43476ccb6)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:188 +0x195
github.com/topfreegames/offers/models_test.TestApi(0xc42009ca80)
/Users/heynemann/Dropbox/dev/go/src/github.com/topfreegames/offers/models/models_suite_test.go:24 +0x64
testing.tRunner(0xc42009ca80, 0x596db8)
/usr/local/Cellar/go/1.7.4_2/libexec/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
/usr/local/Cellar/go/1.7.4_2/libexec/src/testing/testing.go:646 +0x2ec
Any ideas on what's going on? It makes me uneasy to see that whenever a referential integrity error happens.
The latest tag on the v1
branch was created on January, and some work has been done since then, which can't be used. In fact, gopkg locks the package at the latest known tag.
This prevents me from being able to access the Interpolate
func in the runner
package for instance.
Implement caching using Redis.
type Cacher interface {
// Cache caches the result of a Select or SelectDoc. If id is not provided, an FNV checksum
// of the SQL is used as the id. (If interpolation is set, arguments are hashed). Use invalidate to
// immediately invalidate the cache to force setting its value.
Cache(id string, duration time.Duration, invalidate bool)
}
// cache pre-defined game information for a week
DB.SelectDoc("*").
From("games").
Cache("games", 7 * 24 * time.Hour, false).
QueryStruct(&games)
// cache user information for 30 seconds
DB.SelectDoc("*").
From("users").
Where("user_id = $1", id).
Cache("", 30 * time.Second, false).
QueryStruct(&user)
// invalidates cache for key "games"
DB.InvalidateCache("games")
// invalidates all
DB.InvalidateCache(")
Would nice to be able to do a SELECT EXISTS query without using string formatting
var trueFalse bool
sql := fmt.Sprintf("SELECT EXISTS(SELECT 1 FROM orders WHERE user_id = %v)", userId)
err := db.SQL(sql).
QueryScalar(&trueFalse)
I don't get integrity errors reported in the error return value from DB.Exec() and friends when I disable logs with:
LOGXI=-dat.*
I use custom exception in my db (postgresql) like this
get diagnostics n = row_count;
if n = 0 then raise exception 'banjo_operations_delete(): operation [%] does not exist', id; end if;
and this is my backend call
if _, err := rcv.db.SQL(sql, id, c.Name, c.Title).Exec(); err != nil { return err }
and this raise panic err. Can You tell me what's the problem?
I'm using v2 version of dat and MustInterpolate
is mentioned only in documentation, I can't find it anywhere in the code. And without it queries end up with $brj$
spliced in.
What's correct way of doing IN queries and what project branch is most actively developed at the moment?
To enable things like
ORDER BY table.col <-> $1
I have a struct like this
type JSON map[string]interface{}
type Data struct {
ID string `db:"id" json:"id,omitempty"`
meta JSON `db:"meta" json:"meta,omitempty"`
}
But When I try to insert it it gives this error sql: converting Exec argument #7's type: unsupported type common.JSONO, a map
Is there some way to overcome this because I want this meta to be serialized to a string and then stored?
Half the query functions in dat use the standard "sql.ErrNoRows" and half use "dat.ErrNotFound". Could you please just standardize on "sql.ErrNoRows" and drop "dat.ErrNotFound", so we can stop having to guess which is which or testing for both all the time?
I'm getting the following error when pulling v1. Any suggestions welcome and solicited.
$ go get -u gopkg.in/mgutz/dat.v1
package gopkg.in/mgutz/dat.v1: no buildable Go source files in /Users/jmick200/Dropbox/JMickJrRoot/MyDev/dropbox_cc/repo_yggdrasil/src/gopkg.in/mgutz/dat.v1
I was trying to figure out why dat.NullTime
instances were being inserted as the 0 value instead of NULL when EnableInterpolation
is true. It turns out it's because interpolating prefers the Interpolator
interface to the Valuer
interface, and dat.NullTime
implements this here: https://github.com/mgutz/dat/blob/v1/types.go#L264.
Besides the fact that it should definitely return NULL if the time is not valid, I'm not sure why it implements the interpolator interface in the first place. Is the default serialization of time.Time
not sufficient? If you remove that function, NULLs work correctly and times get serialized, but I'm unclear if they're being serialized in the same manner or not.
First of all, thank you for this great library.
But I have encountered one problem. Dat cannot populate nested json with single trip to Postgres.
I have some nested structs (simplified):
type Item struct {
ID int `db:"id" json:"id"`
Name string `db:"name" json:"name"`
CatalogPart ItemCatalogPart `json:"catalog_part"`
}
type ItemCatalogPart struct {
Description string `db:"description" json:"description"`
Fields []ItemField `json:"fields"`
}
type ItemField struct {
ID int `db:"id" json:"id"`
Value string `db:"value" json:"value"`
}
And I trying to query Item with SelectDoc:
func (repo *DBItemRepo) FindByID(id int) (item domain.Item) {
repo.dbHandler.
SelectDoc("id", "name").
One("catalog_part", "SELECT description FROM items AS i WHERE i.id = items.id").
Many("fields", "SELECT id, value FROM item_fields WHERE item_id = items.id ORDER BY id").
From("items").
Where("id = $1", id).
QueryStruct(&item)
return
}
Of course I get nil. How to do it with one trip to DB?
Thank you.
Writing things like dat.NullString{sql.NullString{"foo", true}}
is a tad unwieldy, having helpers like dat.NullStringFrom("foo")
would be awesome (inspiration from https://github.com/guregu/null).
I can have a PR for this in a few days if you think its a good idea,
I would have submitted #5 with a test case, except the "github.com/mgutz/godo/v2"
repo is private so I cannot run the tests.
Hi thanks for the excellent lib. I was wondering if there's a reason why Execer
-> QueryStructs
accepts interface{}
instead of []interface{}
. It should be pretty safe to assume a slice should always be passed to this method and I originally had mistyped it as just QueryStruct
leading to a quite confusing error at runtime. If we can detect this type of mistake at compile time it will be much better.
SelectDoc
combined with QueryJSON
includes row_to_json
in each object
Given the following schema
-- SQL Setup
CREATE TABLE product_prototypes (
id bigserial PRIMARY KEY,
name text NOT NULL
);
INSERT INTO product_prototypes (name) VALUES ('Beer'), ('Wine'), ('Liquor'), ('Extras');
Running this code.
package main
import "gopkg.in/mgutz/dat.v1/sqlx-runner"
func main() {
db := runner.NewDBFromString("postgres", "postgres://localhost/dat_test?sslmode=disable")
b, err := db.SelectDoc("id, name").From("product_prototypes").QueryJSON()
if err != nil {
panic(err)
}
println(string(b))
}
// Actual Output
[
{"row_to_json":{"id":1,"name":"Beer"}},
{"row_to_json":{"id":2,"name":"Wine"}},
{"row_to_json":{"id":3,"name":"Liquor"}},
{"row_to_json":{"id":4,"name":"Extras"}}
]
// Expected Output
[
{"id":1,"name":"Beer"},
{"id":2,"name":"Wine"},
{"id":3,"name":"Liquor"},
{"id":4,"name":"Extras"}
]
First of all, thanks for the logxi library! Been using it for quite some time now.
Dat looks very promising since I'm already using both logxi and sqlx, but what's the state of v2? Should I start using it right away or should I wait?
Best regards, Christoffer
Hello,
after yesterdays commit with logxi, we can no longer build our application.
It says:
gopkg.in\mgutz\dat.v1\init.go:7:2: no buildable Go source files in .....\github.com\mgutz\logxi
We tried deleting all packages and installing them again, updating, etc. Same error everytime.
Could you check it out please?
Thank you
This is more a feature request than an issue, but I wish you'd remove the requirement for Glide. You should leave the vendoring up to the application utilizing your package, since vendoring isn't "inherited".
You've utilized Glide-specific functionality in your code (subpackages), which means if our application doesn't use Glide (it doesn't), we have to take extra manual steps which aren't easily reproducible locally for development and updates or remotely during continuous integration, etc.
The query syntax is pretty nice, but it would be nice to not have to every expression as a string. Specifically, for the Where()
.
What do you think of this form:
err = sess.Select("*").From("posts").Where(dat.Cond{"id >", 100}).QueryStructs(&posts))
dat.Cond is defined as:
type Cond map[string]interface{}
and the cool thing is you can easily have cond := dat.Cond{} and then do cond["field"] = "val"
and then build the condition string as you build the entire query.
if .Where()
accepted an ...interface{}
then both forms could easily be supported. Or leave .Where() and add .Scope() or .WhereCond(), ...
also, is Select("*") implied?
Upsert generates sql with table name in double quotes. Postgres thinks it's relation, not the table name.
After running godo createdb in OSX with iterm the terminal no longer echos characters. Can work-around by running reset
, but still confusing/annoying.
hi, man
There are two problem in README Getting Started part
UpdatedAt dat.Nulltime
db:"updated_at"should be
UpdatedAt dat.NullTime db:"updated_at"
the t should be Uppercase.env: mac 10.10 golang1.4.2
Hello @mgutz! I've noticed this project has gone stale recently. Any updates on project status?
I have some tests that verify my application behaves properly when there are database issues. I found that on head these tests not only fail but end the test run due to the call to a call to logger.Fatal
(
Line 51 in 12949df
panic
in logxi.
It's recommended to avoid exposing panics to consumer of a package and instead return an error so the consumer can choose how to deal with it. https://github.com/golang/go/wiki/PanicAndRecover#usage-in-a-package
On a related note, I noticed there are also some uses of log.Fatalf
in sqlx-runner/db.go
and sqlx-runner/tx.go
. These call os.Exit(1) and should be avoid for similar reasons.
When using schemas, table names are quoted incorrectly by dat in the builders. For example:
db.Update("hello.world").Set("name", "John Doe").Where("id = $1", 23).Exec()
Generates a query that looks like:
update "hello.world" set "name" = 'John Doe' where "id" = 23
It should be:
update "hello"."world" set "name" = 'John Doe' where "id" = 23
That would be really nice to have.
With vendor/
on by default in Go 1.6, it would be really convenient if dat used it for it's dependencies. We use glide for our dependency management, which will trace our dependencies (including dat) if they implement a vendor folder, or use Glide, godep, GB or GPM.
type Realm struct {
RealmUUID types.UUID `db:"realm_uuid"`
}
type Group struct {
GroupUUID types.UUID `db:"group_uuid"`
*Realm
}
...
_, err = conn.InsertInto("groups").Columns("group_uuid", "realm_uuid").Record(g).Exec()
---
panic: could not map db column "realm_uuid" to struct field (use struct tags) [recovered]
panic: could not map db column "realm_uuid" to struct field (use struct tags)
...
_, err = conn.InsertInto("groups").Whitelist("*").Record(g).Exec()
---
2015/05/07 05:28:53 <model.Group Value> must have db struct tags for all fields: `db:""`
Where I'm wrong?
When using Update(...).SetBlacklist(...), the reflection methods fail to traverse into embedded structs with the error message:
<xxx Value> must have db struct tags for all fields: db:""
It seems there is a use of reflectx throughout the dat package which understands struct traversal, but the update methods use their own reflection.
For example:
type Model struct {
ID string `json:"id" db:"id"`
CreatedAt time.Time `json:"createdAt" db:"created_at"`
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
}
type Customer struct {
Model
First string `json:"first" db:"first"`
Last string `json:"last" db:"last"`
}
customer := Customer{}
err := tx.
Update(TableCustomers).
SetBlacklist(customer, "id", "created_at", "updated_at").
Where("id = $1", customer.ID).
Returning("updated_at").
QueryScalar(&customer.UpdatedAt)
Not only that, but it fails with a panic which takes everything down with it.
Hey @mgutz do you think you could make MustPing receive an optional parameter (with ...) to specify a timeout?
The issue I'm trying to avoid is that upon launching my servers, if there's no connectivity to a database, they'll just stay there trying indefinitely to connect, silently. The behavior I would expect of a well-behaved server is to fail with the proper error ("Could not connect to database at somethingsomething:3845" or something like that). That would trigger our error handling infrastructure and we'd be notified.
Do you think this is something you'd like to support? I can contribute with a PR if you'd like.
When I run godo test
I get the following:
22:10 $ go test
--- FAIL: TestInsertRecordsToSql (0.00s)
Error Trace: insert_test.go:63
Error: Not equal: []interface {}{1, 88, false, 2, 99, true} (expected)
!= []interface {}{1, 88, false, 2, 99, true} (actual)
--- FAIL: TestInsertWhitelist (0.00s)
Error Trace: insert_test.go:74
Error: Not equal: []interface {}{1, 88, false, 2, 99, true} (expected)
!= []interface {}{1, 88, false, 2, 99, true} (actual)
--- FAIL: TestInsertBlacklist (0.00s)
Error Trace: insert_test.go:89
Error: Not equal: []interface {}{88, false, 99, true} (expected)
!= []interface {}{88, false, 99, true} (actual)
--- FAIL: TestUpdateWhitelist (0.00s)
Error Trace: update_test.go:79
Error: Not equal: []interface {}{2, false} (expected)
!= []interface {}{2, false} (actual)
--- FAIL: TestUpdateBlacklist (0.00s)
Error Trace: update_test.go:90
Error: Not equal: []interface {}{2, false} (expected)
!= []interface {}{2, false} (actual)
FAIL
exit status 1
FAIL github.com/mgutz/dat 0.011s
I vaguely remember having an issue with this a while back when testify added assert.EqualValues
, what version of github.com/stretchr/testify
are you using?
See e.g. here.
Hi,
Upon adding a new column to a table that was already large I started experiencing index out of range at
https://github.com/mgutz/dat/blob/v1/update.go#L178
It seems the condition that triggers hand off between preallocated parameter conversions and ad hoc conversions may be off by one. If I change i < maxLookup
to i < maxLookup - 1
everything works fine but not sure if that's right, as the last element in equalsPlaceholderTab
will not be used. Also, is it right that equalsPlaceholderTab
starts with $0
?
I wrote a little snippet to test for various values of maxLookup (https://github.com/mgutz/dat/blob/v1/init.go#L19):
type TestStruct struct {
ID int64 `db:"id"`
Field1 string `db:"field1"`
Field2 string `db:"field2"`
}
func TestBreak() {
DB.SQL(`CREATE TABLE testtable (id serial, field1 text, field2 text);`).Exec()
DB.SQL(`INSERT INTO testtable (field1, field2, field3) VALUES ('a', 'b');`).Exec()
record := TestStruct{}
_, err := DB.
Update("testtable").
SetWhitelist(record, "*").
Where("id = $1", 1).
Exec()
if err != nil {
panic(err)
}
DB.SQL(`DROP TABLE testtable;`).Exec()
}
This breaks for maxLookup <= 3
but works for larger values.
Cheers,
Luis
Probably a noob question, but I'm getting this when trying to get started with this package:
vendor/gopkg.in/mgutz/dat.v1/init.go:7:2: no buildable Go source files in /Users/trustmaster/go/src/github.com/mgutz/logxi
Seems like logxi
needs a versioned import there.
jack@hk-2~/dev/go/src/github.com/mgutz/dat$ godo test
PASS
ok github.com/mgutz/dat 0.010s
2015/02/25 07:53:54 Failed to execute statement:
CREATE TABLE people (
id SERIAL PRIMARY KEY,
amount money,
doc hstore,
email text,
foo text default 'bar',
image bytea,
key text,
name text NOT NULL,
created_at timestamptz default now()
)
Got error: pq: type "hstore" does not exist
exit status 1
FAIL github.com/mgutz/dat/sql-runner 0.031s
2015/02/25 07:53:55 Failed to execute statement:
CREATE TABLE people (
id SERIAL PRIMARY KEY,
amount money,
doc hstore,
email text,
foo text default 'bar',
image bytea,
key text,
name text NOT NULL,
created_at timestamptz default now()
)
Got error: pq: type "hstore" does not exist
exit status 1
FAIL github.com/mgutz/dat/sqlx-runner 0.015s
test 3098ms
Perhaps godo createdb should create extension hstore.
We had to disable error logging coming from dat- especially since some queries are extremely long and we don't want to print them when a query crashes. Doing so started generating pointer dereferences in sqlx-runner/execer.go
when trying to access res.RowsAffected
, meaning res
is nil
.
Doing some digging, it turns out the exec
function is returning nil
for both values, even when an error should be returned. In fact, logSQLError
now seems to be returning nil
, even if the parameter isn't.
Our environment variable is set to LOGXI=dat*=OFF
.
I'm not sure if this is an intended behavior of the logger, but it is generating some extremely bad side-effects on our production environment.
DB
-- SQL Setup
CREATE TABLE product_prototypes (
id bigserial PRIMARY KEY,
name text NOT NULL
);
Running (select with no results)
package main
import "gopkg.in/mgutz/dat.v1/sqlx-runner"
func main() {
db := runner.NewDBFromString("postgres", "postgres://localhost/dat_test?sslmode=disable")
b, err := db.SelectDoc("id, name").From("product_prototypes").QueryJSON()
if err != nil {
panic(err)
}
println(string(b))
}
returns a DB error
ErrNoRows == errors.New("sql: no rows in result set")
http://golang.org/pkg/database/sql/
Is this intentional? Would think you'd want to not perform the scan if the result set was empty
Minimal test case here here.
It gives panic: missing destination name user_id
when it should populate the embedded struct.
dat_test=# create table test (time timestamp without time zone NOT NULL DEFAULT (now() AT TIME ZONE 'utc'), name TEXT NOT NULL);
CREATE TABLE
dat_test=# insert into test (name) VALUES('Hello');
INSERT 0 1
dat_test=# select row_to_json(fields.*) FROM (SELECT * FROM test) as fields;
row_to_json
------------------------------------------------------
{"time":"2016-03-02T10:30:26.256081","name":"Hello"}
(1 row)
It seems like that postgres, at least with version 9.5, if using a row without timestamp without time zone
reports the data in the above format
When adding "2006-01-02T15:04:05.000000" to the supported formats, in types.go, it works
Edit: Additional note: this happens when using SelectDoc only of course but I think that's clear to you when you see the row_to_json
I'm using glide as recommended, but the issue is still actual
vendor/gopkg.in/mgutz/dat.v1/init.go:7:2: no buildable Go source files in /Users/green/golang/src/github.com/mgutz/logxi
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.