jet
jet copied to clipboard
Use alias tag to skip destination field during scan
Hey y'all, I was wondering if it is possible to skip certain fields while scanning rows into a destination.
I think there could be two potential solutions that could work together:
type Model struct {
ID string `sql:"primary_key" alias:"model.id"`
Complex *ComplexStruct `alias:"-"` // skip this one
}
Or alternatively as a method on the QRM that only scans fields tagged with alias or sql
stmt.QueryWithTag(db, &rows, map[string]string{ "alias": "json", "sql": "sql" }) // override alias to json
stmt.QueryWithTagOption(db, &rows, Tags.DEFAULT, TagOptions.PERMISSIVE) // default behavior
stmt.QueryWithTagOption(db, &rows, Tags.DEFAULT, TagOptions.STRICT) // only 'alias' or 'sql'
If there isn't a way currently I can take a crack at it.
Hi @gnz00 . The first solution is already implemented - wiki.
If you set alias:"-" for a field, that field will be ignored from the scan. It doesn't have to be "-" it can be any string, but it has to be different from sql query projection alias.
Edit: I just realized I was embedding the struct! Nevermind!
@go-jet Actually, I may have closed this prematurely.
Here is a full example showing a panic:
package main
import (
"database/sql"
"fmt"
"net/http"
mysql "github.com/go-jet/jet/v2/mysql"
_ "github.com/go-sql-driver/mysql"
)
type TestObject struct {
Header http.Header `alias:"-"`
ID string `sql:"primary_key" alias:"id"`
}
func main() {
db, err := sql.Open("mysql", "root:pass@/mysql")
if err != nil {
panic(err)
}
var rows []*TestObject
table := mysql.NewTable("mysql", "user", "", mysql.StringColumn("id"))
mysql.
SELECT(
mysql.RawString("12345").AS("test_object.id"),
).
FROM(table).
Query(db, &rows)
for _, row := range rows {
fmt.Printf("%v\n", row)
}
}
❯ go run main.go
panic: jet: unsupported dest type: Header http.Header
goroutine 1 [running]:
github.com/go-jet/jet/v2/qrm.mapRowToDestinationPtr(0x1024920a0?, {0x140001345c0, 0x31}, {0x10248f260?, 0x1400012c390?, 0x1?}, 0x140001b5730)
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/qrm/qrm.go:336 +0x13c
github.com/go-jet/jet/v2/qrm.mapRowToDestinationValue(0x102474940?, {0x140001345c0, 0x31}, {0x1024920a0?, 0x1400012c390?, 0x102380afc?}, 0x14000132420?)
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/qrm/qrm.go:308 +0x114
github.com/go-jet/jet/v2/qrm.mapRowToStruct(0x14000132420, {0x140001345c0, 0x31}, {0x10244d4a0?, 0x1400012c390?, 0x1400011fd40?}, 0x14000195938?, {0x0?, 0x0, 0x1400011b580?})
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/qrm/qrm.go:241 +0x450
github.com/go-jet/jet/v2/qrm.mapRowToSlice(0x14000132420, {0x0, 0x0}, {0x102449b60?, 0x1400012c348?, 0x0?}, 0x0)
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/qrm/qrm.go:168 +0x2d4
github.com/go-jet/jet/v2/qrm.queryToSlice({0x1024a5c20?, 0x14000124000?}, {0x1024a4228?, 0x14000121790?}, {0x14000134540?, 0x14000134540?}, {0x0?, 0x0?, 0x14000195b68?}, {0x102449b60?, ...})
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/qrm/qrm.go:124 +0x26c
github.com/go-jet/jet/v2/qrm.Query({0x1024a5c20, 0x14000124000}, {0x1024a4228?, 0x14000121790?}, {0x14000134540, 0x35}, {0x0, 0x0, 0x0}, {0x102449b60?, ...})
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/qrm/qrm.go:29 +0x130
github.com/go-jet/jet/v2/internal/jet.(*serializerStatementInterfaceImpl).QueryContext.func1()
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/internal/jet/statement.go:102 +0x5c
github.com/go-jet/jet/v2/internal/jet.duration(0x14000195d88)
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/internal/jet/statement.go:181 +0x3c
github.com/go-jet/jet/v2/internal/jet.(*serializerStatementInterfaceImpl).QueryContext(0x14000132310, {0x1024a5c20, 0x14000124000}, {0x1024a4228, 0x14000121790}, {0x102449b60, 0x1400012c348})
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/internal/jet/statement.go:101 +0x144
github.com/go-jet/jet/v2/internal/jet.(*serializerStatementInterfaceImpl).Query(0x0?, {0x1024a4228?, 0x14000121790?}, {0x102449b60?, 0x1400012c348?})
/Users/gnz00/go/pkg/mod/github.com/go-jet/jet/[email protected]/internal/jet/statement.go:90 +0x58
main.main()
exit status 2
http.Header is a map type. Scan currently supports only base types, structs, arrays and types that implements Scanner interface.
Also, I don't think http.Header is intended to be used directly as part of the response body. Header values are usually just added to ResponseWriter - https://pkg.go.dev/net/http#ResponseWriter
It’s a contrived example but regardless of the type shouldn’t it be skipped with a tag of alias:”-“. I don’t think the expected behavior as you’ve described is a panic.
Setting alias to "-", it doesn't mean that field should be skipped. It just means those type fields should expect projection in form "-.
Now, regarding the destination with a map. I guess we could just ignore the map, without panic.
I am suggesting that there be a token value that will explicitly opt out a field out of projection, as currently I am having to scan and then wrap to avoid panics on embedded 3rd-party structs. Alternatively, if there is no such projection for -, I imagine it should also avoid trying to map it (and evaluating the type, leading to a panic or error otherwise).
You don't have to scan into whole complex destination. For instance:
type Response struct {
Header map[string]string
ThirdParty ThirdParty
Data struct {
model.Actor
Films []model.Film
}
}
Only Data field is set by database query, so only Data field needs to be used as a QueryContext destination. Thus effectively ignoring other fields (Header and ThirdParty).
var response Response
err := stmt.QueryContext(ctx, db, &response.Data)