data-api-builder icon indicating copy to clipboard operation
data-api-builder copied to clipboard

[Bug]: Incorrect parsing of default values when GQL context variables are used

Open ayush3797 opened this issue 1 year ago • 6 comments

Consider the table definition for type_table:

image

The column float_types is a column which has a default value of 1.1. Now, if we execute a GQL create mutation on this table and:

  1. Provide input using GQL context variables
  2. Omit value for the float_types column (since it has a default value so we don't need to specify it)

We get an error:

{
  "errors": [
    {
      "message": "Float cannot parse the given literal of type `StringValueNode`.",
      "path": [
        "item",
        "float_types"
      ],
      "extensions": {
        "field": "CreateSupportedTypeInput.float_types",
        "fieldType": "Float"
      }
    }
  ]
}
image

Similar behavior was observed when int_types was given a default value.

ayush3797 avatar Mar 05 '24 13:03 ayush3797

The only way I got the request to succeed was to set the variable's content to:

{
    "item": {
        "int_types": 1,
        "float_types": 3.1,
        "uuid_types": "e4826b30-1cbb-4ee1-b09e-b76205a77074"
        }
}

seantleonard avatar May 07 '24 17:05 seantleonard

Exception stack trace which indicates that HotChocolate detects that only some of the fields of the mutation are provided and attempts to resolve default values for the remainder of the fields. This violates our assumption that nullable fields are left null. As a result, my current hypothesis is that our GraphQL schema creation may have added default values..

Image

seantleonard avatar May 07 '24 17:05 seantleonard

Yes our schema creation added default value directives. But the Types look inaccurate. I see "String" type which aligns with error message from hot chocolate:

Image

seantleonard avatar May 07 '24 17:05 seantleonard

SchemaConverter::CreateValueNodeFromDbObjectMetadata(object metadataValue) at fault

The caller passes in DatabasePrimitives.ColumnDefinition.DefaultValue which doesn't preserve the actual type of the value.

Image

Then most likely hits the conversion for string before the actual number types:

Image

seantleonard avatar May 07 '24 17:05 seantleonard

We need to use the code written in #1883 to handle the following default values returned by sql and create a function to remove parenthesis in default values:

// Remove parens:
// 1. built_in funtions are surrounded by single parenthesis,i.e. (getdate())
// 2. string will be with parenthesis and single quotes, i.e. ('value')
// 3. int/float will be with double parenthesis, i.e. ((20))

The current form of default value looks to always be a string due to the parens. not sure why this doesn't fail requests that don't provide GraphQL parameters and provide field values for mutations directly in requests.

seantleonard avatar May 07 '24 18:05 seantleonard

This change is more involved and would benefit from sufficient time to test and devise an appropriate solution for all database types because all database types utilize default values but their SDKs (SQL Client and mysql/pg equivalent may return default values differently).

seantleonard avatar May 07 '24 18:05 seantleonard