-
Notifications
You must be signed in to change notification settings - Fork 116
go {livesql,sqlgen,internal}: support []byte arguments for live queries #172
Conversation
Pull Request Test Coverage Report for Build 1088
💛 - Coveralls |
8acdee9
to
a129e23
Compare
users := make(chan *User) | ||
rerunner := reactive.NewRerunner(context.Background(), func(ctx context.Context) (interface{}, error) { | ||
user := &User{} | ||
if err := db.QueryRow(ctx, &user, sqlgen.Filter{"mood": &mood}, nil); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means UUIDs should definitely work
livesql/integration_test.go
Outdated
|
||
// We use a channel to pass around query updates for testing. | ||
users := make(chan *User) | ||
rerunner := reactive.NewRerunner(context.Background(), func(ctx context.Context) (interface{}, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try using batch.WithBatching(ctx)
cute idea: check reflect.Type.Comparable() |
a129e23
to
74ba38d
Compare
// [...]interface{} for use as a comparable map key | ||
// | ||
func ToArray(s []interface{}) interface{} { | ||
func MakeHashable(s []interface{}) interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can do the byte to string conversion at a higher level where we create the byte slices
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern would be breaking things at the SQL layer if I put it higher up. If I were to pick out a refactor that could be worth doing, it's making the filter more responsible for its various conversions so that we don't have to hold in our heads what these things ^ are used for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like batching doesn't actually use the driver.Value
. Need to find a way to do so.
internal/reflect.go
Outdated
// Convert byte slices into strings as they are otherwise not comparable/hashable. | ||
for i, elem := range s { | ||
if b, ok := elem.([]byte); ok { | ||
s[i] = string(b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be a type Alias of string
74ba38d
to
fd36c92
Compare
fd36c92
to
91e52b8
Compare
@stephen I'm ready to merge this as soon as I have a 👍 |
91e52b8
to
4cf03cf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add a little context in the PR description for what isn't supported? Think I understand the changes being made, but not the context for what we see that's breaking.
// fast code paths for short arrays: | ||
case 0: | ||
return [...]interface{}{} | ||
case 1: | ||
return [...]interface{}{s[0]} | ||
return [...]interface{}{d[0]} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit: consider changing out s
-> d
in the arguments instead so that these references stay the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(i also checked find all references so this seems fine as is)
@@ -31,34 +31,44 @@ func init() { | |||
interfaceTyp = reflect.TypeOf(&x).Elem() | |||
} | |||
|
|||
// ToArray converts a []interface{} slice into an equivalent fixed-length array | |||
// MakeHashable converts a []interface{} slice into an equivalent fixed-length array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: consider doing the rename in a separate step to make the semantic change easier to read
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
## Problem We have UUIDs which use or convert to `[]byte`. Both livesql and the batcher rely on comparable/hashable values (values that are put into a `map`) to work and panic otherwise. This means that we can't use those custom types with livesql or batching. ## Solution ### LiveSQL The `ToArray` function has been used for creating hashable/comparable arguments in the past. Renamed it to be more explicit, and also handle `[]byte` arguments, converting them into strings. The primary use-case for this PR is to support UUIDs. We also get support for anything else that turns into `[]byte`. The reason we want to serialize our arguments/filters is because (unfortunately) we support type aliases in our filters, and therefore allow you to query a `int64` with `int`/`int8`/etc. In order to maintain backward compatibility there, we have to assume that we're dealing with a SQL value for caching/rerunning. ### Batching TL;DR: do nothing Batching deals with go struct types (not go sql types), which means we have many possible permutations of types. We _could_ take our filter values and convert them to their sql values, using that to compare. This would take more time than simply using a `[16]byte` for our UUIDs. It would properly implement 100% compatibility with custom types. However, I have some concerns about performance in doing so, and given deadline constraints, we can add that on later rather than doing so now. **Slices in filters will continue not to be supported for batching.**
This method name makes it clearer what the intention is behind the method, rather than just documenting behavior.
4cf03cf
to
0d64f47
Compare
Problem
We have UUIDs which use or convert to
[]byte
. Both livesql and the batcher rely on comparable/hashable values (values that are put into amap
) to work and panic otherwise. This means that we can't use those custom types with livesql or batching.Solution
LiveSQL
The
ToArray
function has been used for creating hashable/comparable arguments in the past. Renamed it to be more explicit, and also handle[]byte
arguments, converting them into strings.The primary use-case for this PR is to support UUIDs. We also get support for anything else that turns into
[]byte
.The reason we want to serialize our arguments/filters is because (unfortunately) we support type aliases in our filters, and therefore allow you to query a
int64
withint
/int8
/etc. In order to maintain backward compatibility there, we have to assume that we're dealing with a SQL value for caching/rerunning.Batching
TL;DR: do nothing
Batching deals with go struct types (not go sql types), which means we have many possible permutations of types. We could take our filter values and convert them to their sql values, using that to compare. This would take more time than simply using a
[16]byte
for our UUIDs.It would properly implement 100% compatibility with custom types. However, I have some concerns about performance in doing so, and given deadline constraints, we can add that on later rather than doing so now.
Slices in filters will continue not to be supported for batching.