web-ridge / gqlgen-sqlboiler

This is a plugin for gqlgen to generate converts + filter queries and resolvers for sqlboiler
MIT License
74 stars 13 forks source link

Plugin Panics #38

Closed sjhitchner closed 3 years ago

sjhitchner commented 3 years ago

Hey, trying out your library and experiencing a few issues. Looking for help debugging what's going on.

I'm assuming there is something strange with my DB schema (Postgres). Wondering if you can offer any advice on how to debug. Using this library will save me tons of time. Happy to dig in but thought you might see some obvious issues.

When I run the plugin I get the following panic

% go run convert_plugin.go                                                                                                     
[convert] get boiler models
[convert] get extra's from schema
[convert] get model with information
[WARN] boiler name not available for  RecipeBatch.Additives
[WARN] boiler name not available for  RecipeBatch.Fragrances
[WARN] boiler name not available for  RecipeBatch.Lipids
[WARN] boiler type not available for  Lye
[WARN] boiler name not available for  RecipeBatch.Lye
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x130bcda]

goroutine 1 [running]:
github.com/web-ridge/gqlgen-sqlboiler/v2.getConvertConfig(0x0, 0x0, 0x0, 0xc00010d440, 0xc0008fb680, 0x1, 0x13edb77, 0x26, 0xc0008edfa0, 0x17, ...)
    /Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:863 +0x78a
github.com/web-ridge/gqlgen-sqlboiler/v2.enhanceModelsWithFields(0x0, 0x0, 0x0, 0xc00029c5c0, 0xc0000d0c60, 0xc000301400, 0x6c, 0x80)
    /Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:455 +0xa89
github.com/web-ridge/gqlgen-sqlboiler/v2.GetModelsWithInformation(0x0, 0x0, 0x0, 0xc0000d0c60, 0xc000358000, 0x12, 0x12, 0x0, 0x5, 0x8)
    /Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:158 +0xe2
github.com/web-ridge/gqlgen-sqlboiler/v2.(*ConvertPlugin).MutateConfig(0xc0001a4310, 0xc0000d0c60, 0xc0001a4310, 0x27870a8)
    /Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:193 +0x491
github.com/99designs/gqlgen/api.Generate(0xc0000d0c60, 0xc0000eff48, 0x2, 0x2, 0x1, 0x1)
    /Users/steve/go/pkg/mod/github.com/99designs/gqlgen@v0.13.0/api/generate.go:65 +0x676
main.main()
    /Users/steve/src/github.com/sjhitchner/soapcalc/backend/convert_plugin.go:34 +0x255
exit status 2

There is panic is because field.BoilerField.Relationship.Name is nil. Should this ever happen? https://github.com/web-ridge/gqlgen-sqlboiler/blob/main/convert.go#L863

I wrapped that line in a nil check to stop the panic but get the following error when I run the plugin again.

[resolver] generate file
error!!
resolvergen: convert.gotpl: template: convert.gotpl:27:19: executing "convert.gotpl" at <$.Backend.Directory>: can't evaluate field Backend in type *gqlgen_sqlboiler.ResolverBuild
exit status 3

This is the plugin configuration

    output := gbgen.Config{
        Directory:   "generated/graphql/helpers",
        PackageName: "helpers",
    }
    backend := gbgen.Config{
        Directory:   "generated/db/models",
        PackageName: "models",
    }
    frontend := gbgen.Config{
        Directory:   "generated/graphql/models",
        PackageName: "gmodels",
    }

I used the https://github.com/web-ridge/sqlboiler-graphql-schema library is generate my graphql schema and got a similar nil error https://github.com/web-ridge/sqlboiler-graphql-schema/blob/main/main.go#L714 relationType := boilerField.Relationship.Name Which I changed to relationType := boilerField.RelationshipName

This change successfully generated a valid schema but needed a few edits to deal with pluralizations, and remove relationships that I didn't want to expose.

I could post the DB schema and graphql schema but the files are over 1000 lines.

Library is very cool. Glad to help out debugging!

RichardLindhout commented 3 years ago

This should not happen.

What is the name of the root model, foreign key and the model itself?

Ideally we would have a very small reproduction of the same case.

sjhitchner commented 3 years ago

Thanks for your quick response!

Here is a link to a diagram of my schema. I guess the root model would be named Recipe.
https://github.com/sjhitchner/soapcalc/blob/sqlboiler/soap.png

Made a little progress this evening. Although I'm still getting some nil pointer panics and errors when I run convert_plugin.go

Reread the README and it triggered a thought. I had a self-referential foreign key. I have removed that and that seems to have solved one issue.

When using sqlboiler-graphql-schema I needed to change the below line to relationType := boilerField.RelationshipName otherwise I get a nil pointer panic. Not sure this is the correct change, but the tool no longer panics. https://github.com/web-ridge/sqlboiler-graphql-schema/blob/main/main.go#L714

The schema that is generated is mostly right, but there are some manually changes I need to make for gqlgen to work.

type Lye {
  id: ID!
  kind: String!
  name: String!
  note: String!
  deletedAt: Int
  updatedAt: Int!
  createdAt: Int!
  recipeBatchLye: RecipeBatchLye
  lyeInventories: [LyeInventories]  <=== Should not be type name not pluralized
}

type LyeInventory {
  id: ID!
  purchaseDate: Int!
  expiryDate: Int!
  cost: Float!
  weight: Float!
  concentration: Float!
  lye: Lye!
  supplier: Supplier!
  deletedAt: Int
  createdAt: Int!
  updatedAt: Int!
}
...
input RecipeBatchWhere {
  id: IDFilter
  tag: StringFilter
  productionDate: IntFilter
  sellableDate: IntFilter
  note: StringFilter
  lipidWeight: FloatFilter
  productionWeight: FloatFilter
  curedWeight: FloatFilter
  recipe: RecipeWhere
  deletedAt: IntFilter
  updatedAt: IntFilter
  createdAt: IntFilter
  batchRecipeBatchAdditives: BatchRecipeBatchAdditivesWhere    <===== Prefixed with Batch should be RecipeBatchAdditiveWhere and not plural
  batchRecipeBatchFragrances: BatchRecipeBatchFragrancesWhere
  batchRecipeBatchLipids: BatchRecipeBatchLipidsWhere
  batchRecipeBatchLyes: BatchRecipeBatchLyesWhere
  batchRecipeBatchNotes: BatchRecipeBatchNotesWhere
  or: RecipeBatchWhere
  and: RecipeBatchWhere
}

After the above changes I was able to run convert_plugin.go. It generated a number of helper files but also the below errors.

Still needed to wrap a nil check around this line. https://github.com/web-ridge/gqlgen-sqlboiler/blob/main/convert.go#L863

% go run convert_plugin.go
[convert] get boiler models
[convert] get extra's from schema
[convert] get model with information
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Fragrance.Inventory
[WARN] boiler type not available for  AdditiveInventory
[WARN] boiler name not available for  Supplier.AdditiveInventory
[WARN] boiler type not available for  FragranceInventory
[WARN] boiler name not available for  Supplier.FragranceInventory
[WARN] boiler type not available for  LipidInventory
[WARN] boiler name not available for  Supplier.LipidInventory
[WARN] boiler type not available for  LyeInventory
[WARN] boiler name not available for  Supplier.LyeInventory
[WARN] boiler name not available for  RecipeBatch.Additives
[WARN] boiler name not available for  RecipeBatch.Fragrances
[WARN] boiler name not available for  RecipeBatch.Lipids
[WARN] boiler type not available for  Lye
[WARN] boiler name not available for  RecipeBatch.Lye
[WARN] boiler name not available for  RecipeBatch.Notes
[WARN] boiler type not available for  AdditiveInventory
[WARN] boiler type not available for  FragranceInventory
[WARN] boiler type not available for  AdditiveInventory
[WARN] boiler type not available for  FragranceInventory
[WARN] boiler type not available for  LipidInventory
[WARN] boiler type not available for  LyeInventory
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Additive.Inventory
[WARN] boiler type not available for  LipidInventory
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Lipid.Inventory
[WARN] boiler name not available for  Recipe.Additives
[WARN] boiler name not available for  Recipe.Batches
[WARN] boiler name not available for  Recipe.Fragrances
[WARN] boiler name not available for  Recipe.Lipids
[WARN] boiler name not available for  Recipe.Steps
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Lye.Inventory
[WARN] boiler type not available for  LyeInventory
[convert] render preload.gotpl
[convert] render convert.gotpl
[convert] render convert_input.gotpl
[convert] render filter.gotpl
gofmt failed on filter.go: generated/graphql/helpers/filter.go:373:110: expected selector or type assertion, found ')' (and 1499 more errors)
[resolver] get boiler models
[resolver] get models with information
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Lipid.Inventory
[WARN] boiler name not available for  Recipe.Additives
[WARN] boiler name not available for  Recipe.Batches
[WARN] boiler name not available for  Recipe.Fragrances
[WARN] boiler name not available for  Recipe.Lipids
[WARN] boiler name not available for  Recipe.Steps
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Lye.Inventory
[WARN] boiler type not available for  LyeInventory
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Fragrance.Inventory
[WARN] boiler type not available for  AdditiveInventory
[WARN] boiler name not available for  Supplier.AdditiveInventory
[WARN] boiler type not available for  FragranceInventory
[WARN] boiler name not available for  Supplier.FragranceInventory
[WARN] boiler type not available for  LipidInventory
[WARN] boiler name not available for  Supplier.LipidInventory
[WARN] boiler type not available for  LyeInventory
[WARN] boiler name not available for  Supplier.LyeInventory
[WARN] boiler name not available for  RecipeBatch.Additives
[WARN] boiler name not available for  RecipeBatch.Fragrances
[WARN] boiler name not available for  RecipeBatch.Lipids
[WARN] boiler type not available for  Lye
[WARN] boiler name not available for  RecipeBatch.Lye
[WARN] boiler name not available for  RecipeBatch.Notes
[WARN] boiler type not available for  AdditiveInventory
[WARN] boiler type not available for  FragranceInventory
[WARN] boiler type not available for  Inventory
[WARN] boiler name not available for  Additive.Inventory
[WARN] boiler type not available for  AdditiveInventory
[WARN] boiler type not available for  FragranceInventory
[WARN] boiler type not available for  LipidInventory
[WARN] boiler type not available for  LyeInventory
[WARN] boiler type not available for  LipidInventory
[resolver] generate file
error!!
resolvergen: convert.gotpl: template: convert.gotpl:27:19: executing "convert.gotpl" at <$.Backend.Directory>: can't evaluate field Backend in type *gqlgen_sqlboiler.ResolverBuild
exit status 3

I'm going to scale back the schema and iterate on adding tables to see if I can find where things start breaking.

RichardLindhout commented 3 years ago

Thanks for helping, Ideally we would have a schema with al breaking things added to examples/

https://github.com/web-ridge/gqlgen-sqlboiler-examples

So we can make sure all cases work after a version update

RichardLindhout commented 3 years ago

Can you send my the sql of the table generation? info@webridge.nl so I can look into it this week

sjhitchner commented 3 years ago

I started with a basic schema and adding models and was still running into issues.

I have emailed you a copy of my schema. I got caught up with work today and wasn't able to get much debugging in this evening, should have time tomorrow.

RichardLindhout commented 3 years ago

Thanks for the .sql file I'm reproducing this at: https://github.com/web-ridge/gqlgen-sqlboiler-examples/tree/main/issue-38-plugin-panics

RichardLindhout commented 3 years ago

The graphql schema is not right on the Update/Create inputs where it includes the relationships while there is no id in the input itself.

input FragranceUpdateInput {
    recipeBatchFragrance: RecipeBatchFragrance # should not be here
    recipeFragrance: RecipeFragrance # should not be here
}

I'll try to fix your example this week

RichardLindhout commented 3 years ago

I fixed most issues locally, thanks for providing the schema and the feedback so far! I'm still working on some extra fixes. Do you want the django_ tables in models and graphql_models too? Some tables of them don't have id's.

sjhitchner commented 3 years ago

Cool, thanks for looking into this!

Whoops, I forgot to filter those tables out of the schema I sent you. I've just been using Django to manage migrations and for a simple admin interface. They can be ignored.

RichardLindhout commented 3 years ago

I'll release a new version this evening which generates your database schema correctly.

I'm not sure if the functionality on Fragrance will work correctly since the foreign key is not available in the struct itself. It would be nice if you could test out if

RichardLindhout commented 3 years ago

Here is the output so far: https://github.com/web-ridge/gqlgen-sqlboiler-examples/tree/main/issue-38-plugin-panics

RichardLindhout commented 3 years ago

New versions are released which should fix this issue. Thanks you for helping me to reproduce the issue 👌!

gqlgen-sqlboiler https://github.com/web-ridge/gqlgen-sqlboiler/releases/tag/v2.1.5 sqlboiler-graphql-schema https://github.com/web-ridge/sqlboiler-graphql-schema/releases/tag/v1.0.5

Don't forget to pin https://github.com/web-ridge/utils-go on the latest commit (I still need this to follow the gomodule version spec which is not te case yet, so sometimes it won't pin to the latest version)