99designs / 99designs/gqlgen

gqlgen does not autobind to database models that use types like sql.NullString or sql.NullInt32.

Open
#2,639 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
10.8k
Forks
1.3k
Avg merge
2d 36m
Merged PRs (30d)
26

Description

I am using gqlgen v.0.17.31 (the latest) as of this writing.

I am using gqlgen and also working with sqlc (mysql) to generate database models which is autobinded in the gqlgen.yaml. However, after using gqlgen generate command, the schema.resolvers.go generates unwanted resolvers for my fk_dma_name, call_letters, and channel_num fields which are just basic database columns of types Int and String. Then in the graphiql playground, running a basic GET query (getDetails) for ChannelDetail, I am only able to get back the sk_chnl_details_id field only. When I try to query the fk_dma_name or call_letters or channel_num, it returns a message: internal system error.

my gqlgen schema.graphqls file:
```
type ChannelDetail {
sk_chnl_details_id: Int!
fk_dma_name: String,
call_letters: String,
channel_num: Int,
}

type Query {
getDetails: [ChannelDetail!]!
}
```

my sqlc (mysql) auto-generated models.go file:
```
type ChannelDetail struct {
SkChnlDetailsID int32 `db:"sk_chnl_details_id" json:"sk_chnl_details_id"`
FkDmaName sql.NullString `db:"fk_dma_name" json:"fk_dma_name"`
CallLetters sql.NullString `db:"call_letters" json:"call_letters"`
ChannelNum sql.NullInt32 `db:"channel_num" json:"channel_num"`
}
```

my gqlgen schema.resolvers.go file after I run the gqlgen generate command:

```
// However, I noticed that there is no resolver function created for the sk_chnl_details_id field weirdly

// FkDmaName is the resolver for the fk_dma_name field.
func (r *channelDetailResolver) FkDmaName(ctx context.Context, obj *sqlc.ChannelDetail) (*string, error) {
panic(fmt.Errorf("not implemented: FkDmaName - fk_dma_name"))
}

// CallLetters is the resolver for the call_letters field
func (r *channelDetailResolver) CallLetters(ctx context.Context, obj *sqlc.ChannelDetail) (*string, error) {
panic(fmt.Errorf("not implemented: CallLetters - call_letters"))
}

// ChannelNum is the resolver for the channel_num field.
func (r *channelDetailResolver) ChannelNum(ctx context.Context, obj *sqlc.ChannelDetail) (*int, error) {
panic(fmt.Errorf("not implemented: ChannelNum - channel_num"))
}

// GetDetails is the resolver for the getDetails field for type Query
func (r *queryResolver) GetDetails(ctx context.Context) ([]sqlc.ChannelDetail, error) {
*custom code here
}

-- I included the below default code to paint the whole picture but not necessary to see the problem is the above resolver functions being created for basic database fields or what I think is a problem
// ChannelDetail returns ChannelDetailResolver implementation.
func (r *Resolver) ChannelDetail() ChannelDetailResolver { return &channelDetailResolver{r} }

// Mutation returns MutationResolver implementation.
func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} }

// Query returns QueryResolver implementation.
func (r *Resolver) Query() QueryResolver { return &queryResolver{r} }

type channelDetailResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
```

I was under the impression that gqlgen resolvers functions in schema.resolvers.go only were created for type query or mutation methods or forced explicit fields. Not for basic fields that are just database columns of type String and Int. Is there something I can do on my end to fix this? I only pasted the relevant code, but can provide more details.

Solved: inside the sqlc's generated database model, I had to override manually all the types that were using sql.* types i.e. sql.NullString or sql.NullInt32 to string or int32 respectively. Can we update gqlgen so that it recognizes types like sql.NullString or sql.NullInt32 when turning on the autobind in gqlgen.yaml

Contributor guide

Open the contributing guide

Research direction

Look at the gqlgen code generation logic, particularly the autobinding feature in the gqlgen.yaml configuration. The issue is that sql.NullString and sql.NullInt32 types from the database/sql package are not being recognized as nullable GraphQL String/Int fields. Start by examining the type mapping system in the gqlgen codebase, likely in internal/code or similar directories. Check how Go types are mapped to GraphQL types during generation. The fix would involve updating the type mapping to handle sql.Null* types appropriately, treating them as nullable GraphQL scalars. Test by modifying the type mapping logic and running gqlgen generate against a test schema that uses these types.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend-api-design
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.