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

[FIX] Issue #122 / Add database/sql null type support #200

Open
wants to merge 28 commits into
base: master
Choose a base branch
from

Conversation

quetzyg
Copy link
Contributor

@quetzyg quetzyg commented Mar 14, 2021

Description

This pull request addresses issue #122, which aims to add support for database/sql null types.

I mainly want to start a discussion about the implementation, since there's definitely room for change/improvement.

Also, while pushing my changes, I realised from the TravisCI results that Go versions prior to 1.13 don't have support for database/sql null types. Would bumping the minimum Go version to 1.13 be a deal breaker?

Task items:

  • Response (Marshall):
    • Split the response visitModelNode() function logic, to be more manageable/readable;
    • Move the node ID resolution logic into resolveNodeID();
      • Add support for IDs of the type: sql.NullString, sql.NullInt32, sql.NullInt64 and sql.NullFloat64
    • Move the node attribute resolution logic into resolveNodeAttribute();
      • Add support for attributes of the type: sql.NullTime, sql.NullBool, sql.NullString, sql.NullFloat64, sql.NullInt32 and sql.NullInt64
    • Move the node relation resolution logic into resolveNodeRelation();
  • Request (Unmarshall):
    • Split the request unmarshalNode() function logic, to be more manageable/readable;
    • Move the node ID resolution into unmarshallID();
      • Add support for IDs of the type: sql.NullString, sql.NullInt32, sql.NullInt64 and sql.NullFloat64
    • Add support for attributes of the type: sql.NullTime, sql.NullBool, sql.NullString, sql.NullFloat64, sql.NullInt32 and sql.NullInt64
    • Move the node relation resolution logic into unmarshallRelation();
  • Update/increase test coverage;

… more manageable

- three new functions were created: resolveNodeID(), resolveNodeAttribute() and resolveNodeRelation()
- sql.NullBool
- sql.NullString
- sql.NullFloat64
- sql.NullInt32
- sql.NullInt64
@quetzyg
Copy link
Contributor Author

quetzyg commented Mar 14, 2021

Hi @aren55555,

I would like your opinion on the work done so far.

Cheers!

response.go Outdated
case reflect.Uint64:
node.ID = strconv.FormatUint(v.Interface().(uint64), 10)
case reflect.Struct:
if nStr, ok := v.Interface().(sql.NullString); ok {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Other sql.Null* types don't make sense for an ID, so we only consider: sql.NullString, sql.NullInt32 and sql.NullInt64.

node.Attributes[args[1]] = t.Unix()
}
}
case reflect.TypeOf(sql.NullTime{}):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure how common the usage of *sql.NullTime is (if that even makes sense), so for now I just added support for sql.NullTime.

response.go Outdated

if node.Relationships == nil {
node.Relationships = make(map[string]interface{})
if nI32, ok := fieldValue.Interface().(sql.NullInt32); ok {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't find a DRY way to handle the repetitive checks sql.Null* types require (omit attribute, return null and return value).

node, err = resolveNodeID(node, fieldValue, fieldType)

if err != nil {
return nil, err
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Returning early, instead of breaking and dealing with the error further down.

@aren55555
Copy link
Contributor

Please add tests that verify both the marshaling and unmarshalling behavior of these new types.

…wn functions

- unmarshallID()
- unmarshallRelation()
…() function

- implement isSQLNullType() and handleSQLNullType() functions
@quetzyg quetzyg marked this pull request as ready for review April 2, 2021 15:43

json.NewEncoder(buf).Encode(data.Relationships[args[1]])
json.NewDecoder(buf).Decode(relationship)
func unmarshallID(node *Node, fieldValue reflect.Value, structField reflect.StructField) (*Node, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

unmarshallID isn't the greatest name, so I'm open to suggestions.


func unmarshallRelation(node *Node, fieldValue reflect.Value, included *map[string]*Node, args []string) (*Node, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same here, feel free to suggest a better function name.

if data.Attributes["decimal"] != 3.0 {
t.Fatalf("Error marshalling to sql.NullInt32")
}

Copy link
Contributor Author

@quetzyg quetzyg Apr 2, 2021

Choose a reason for hiding this comment

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

Unlike in the previous test, I'm not checking the expected values of data.Attributes["fractional"] and data.Attributes["computed_at"], since what we're getting doesn't make much sense to me.

I would expect data.Attributes["fractional"] to be 1415926535897932, yet we get 1.415926535897932e+15.
The same goes for data.Attributes["computed_at"], where we get 1.615734e+09 instead of 1615734000.

I'm not sure if this is expected, but it doesn't feel right. I also wonder if this is somehow related to #202, where we get a different float64 when converting values back.

TL;DR; I'm expecting different numeric types (int32 and int64), but get float64 instead.

@wurmrobert
Copy link

Nice feature. Would be great if you merge it into the master.
+1

@quetzyg
Copy link
Contributor Author

quetzyg commented May 19, 2021

Nice feature. Would be great if you merge it into the master.
+1

Yeah, but we need #206 merged first. Ping the repository owner if you have an interest.

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.

3 participants