Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change (*UUID) Scan to accept type UUID argument #58

Merged
merged 1 commit into from
Oct 30, 2018

Conversation

nanjj
Copy link

@nanjj nanjj commented Oct 26, 2018

Type UUID can not used as primary key, which is not NULL in table. Type
NullUUID can be used as reference to the primary key in another table,
which may be NULL. If we use jinzhu/gorm to implement the usage
scenario, jinzhu/gorm convert UUID to NullUUID via NullUUID Scan
call. Without the fix below error may be found: uuid: cannot convert
uuid.UUID to UUID.

This fix changes (*UUID) scan to accept UUID argument.

@codecov-io
Copy link

codecov-io commented Oct 26, 2018

Codecov Report

Merging #58 into master will increase coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #58      +/-   ##
==========================================
+ Coverage   98.91%   98.92%   +0.01%     
==========================================
  Files           4        4              
  Lines         276      279       +3     
==========================================
+ Hits          273      276       +3     
  Misses          2        2              
  Partials        1        1
Impacted Files Coverage Δ
sql.go 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 48eeef7...0ab72f8. Read the comment docs.

@nanjj nanjj force-pushed the sqlscan branch 2 times, most recently from 6131f16 to 1784f78 Compare October 26, 2018 20:59
@acln0
Copy link
Member

acln0 commented Oct 26, 2018

Hello, and thank you for sending this PR! I'm a little bit confused about it though, so please help me understand. The https://golang.org/pkg/database/sql/#Scanner documentation lists the possible types of src, and UUID is not one of those types. Are you hitting a case in which src is of type uuid.UUID? If so, how? Is an ORM involved?

@acln0 acln0 self-assigned this Oct 26, 2018
@nanjj
Copy link
Author

nanjj commented Oct 27, 2018

Yes, I am using jinzhu/gorm, see below structs:

type A struct {
UUID uuid.UUID
}
type B struct {
...
AID uuid.NullUUID
}

AID is NullUUID type (in order to make it nullabe in db), which refer A.UUID( which is UUID since it's primary, which can not be null in db). gorm does not know how to covert UUID to NullUUID so it calls sql scan, which the UUID value passed in NullUUID.

Copy link
Member

@acln0 acln0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like gorm overloads the sql.Scanner interface somewhat suspiciously, but I think we could help with this nevertheless. Doing the check doesn't hurt.

The commit message explains what the problem is, but it doesn't describe the fix. Please start the commit message with a note along the lines of Change (*NullUUID).Scan to accept arguments of type UUID., then, continue with the existing explanation. Also, please drop the backticks from the commit message.

I have one little concern about the code too, which I have left in a comment. Once these are addressed, I would be inclined to merge the PR, but I would also like at least another pair of eyes on it before I do.

sql.go Outdated
@@ -74,6 +74,11 @@ func (u *NullUUID) Scan(src interface{}) error {
return nil
}

if id, ok := src.(UUID); ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the code path at line 84, we delegate to UnmarshalText or UnmarshalBinary, which validate the UUID. Here, we do no such thing, and we take it for granted that if src is of type UUID, then it represents a valid UUID.

In the context of your ORM and its usage, is there ever a world in which this src is not a valid UUID?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case, I think we should leave a comment here, which describes why we are doing this. It should mention that certain ORMs use sql.Scanner to convert Go values to other Go values.

@nanjj nanjj force-pushed the sqlscan branch 2 times, most recently from d35b69d to 8719eca Compare October 29, 2018 16:35
@nanjj nanjj changed the title Make NullUUID Scan UUID Change (*UUID) Scan to accept type UUID argument Oct 29, 2018
@nanjj
Copy link
Author

nanjj commented Oct 29, 2018

@acln0 yes, src can be []byte type or string type in jinzhu/gorm, and can be UUID type.

sql.go Outdated
@@ -38,6 +38,10 @@ func (u UUID) Value() (driver.Value, error) {
// a longer byte slice or a string will be handled by UnmarshalText.
func (u *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case UUID: // support gorm convert from UUID to NullUUID
u = &src
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is almost certainly not right. It changes the pointer u's value, but not the UUID it points to. *u = src.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

sql_test.go Outdated
@@ -193,6 +194,21 @@ func testNullUUIDScanValid(t *testing.T) {
}
}

func testNullUUIDScanUUID(t *testing.T) {
s := UUID{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use the zero value here. It could lead to confusion. Please use codecTestUUID instead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Type UUID can not used as primary key, which is not NULL in table. Type
NullUUID can be used as reference to the primary key in another table,
which may be NULL. If we use jinzhu/gorm to implement the usage
scenario, jinzhu/gorm convert UUID to NullUUID via NullUUID Scan
call. Without the fix below error may be found: uuid: cannot convert
uuid.UUID to UUID.

This fix changes (*UUID) scan to accept UUID argument.
Copy link
Member

@acln0 acln0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks.

I will merge this once someone else approves it too.

@niaow niaow self-requested a review October 30, 2018 01:20
Copy link
Member

@niaow niaow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@acln0 acln0 merged commit 7077aa6 into gofrs:master Oct 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants