Examples: https://www.c-sharpcorner.com/article/writing-complex-querie...
The hard bit here is making sure the language type-checker is fully aware of the involved types, both while writing the query as well as while selecting the results to be returned
This approach has since been copied in more capable languages. One of my favorite examples lately is Rust's Diesel: https://diesel.rs/ (see the "complex queries") example.
A query language designer aware of the above lessons learned with SQL might take special care to ensure their new query language is easier to model in existing languages. For example, they might consider an alternative OOP or FP based syntax, or to generalize they might put some thought into what would make it easy to write a type-safe query builder. After all, while SQL was developed in 197x and we had a different model for data access early on (stored procedures instead of flexible language-integrated queries) so its easier to understand that we didn't consider integration with other languags. TypeScript already did exist when GraphQL first appeared in 2015, and it's been 7 years of LINQ at that point.
Yet, we still went the stored procedures route. Tools such as graphql-codegen [1] require you to regenerate your types every time you edit your query strings
At this point I'm pretty sure you're conflating the underlying technology with what a wrapper could do on top of it. And in that regard I absolutely agree with you: raw GraphQL doesn't make any sense, the same way raw SQL (in 2022) doesn't make sense either.
EDIT (mandatory before I get lynched lol): except in cases where the wrapper builds a query that is inefficient or should be tweaked manually.
Could you give me an example of a good client wrapper that doesn't require you to write queries as strings?
To make it clear, I disagree I'm conflating things. I'm currently working on a TypeScript based graphql builder (https://typed-graphql-builder.spion.dev/) and I can think of several ways the language could've been designed to make it easier to write typed query builders.
This is not without consequences - since its quite hard to write the builder, most tools available for code generation (https://www.graphql-code-generator.com/) are built around editing GraphQL strings and will try to find them in your code and add type assertions. Additionally the rest of the ecosystem tools are built around supporting this workflow (graphql playgrund, etc)
Would you like to share them? Have you tried submitting your suggestions to the GraphQL core team?
Here is a few:
- Less fine-grained field selection - allow for fields selected by default. This would remove some of the need for optionals in languages that aren't able to dynamically create record types on the fly
- Implicit unions and union queries are really annoying to model in both OOP and FP languages. In FP disjoint tagged unions with no inheritance would work better; in OOP common interfaces but no ability to define unions would work better. As it stands, the mix makes it difficult on both language types to support a general schema. Unions based on optional fields (like in GRPC) are probably best-of-both-worlds here.