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

Allow the specification of shared row datatypes #3595

Open
pconstantinou opened this issue Sep 10, 2024 · 0 comments
Open

Allow the specification of shared row datatypes #3595

pconstantinou opened this issue Sep 10, 2024 · 0 comments
Labels
enhancement New feature or request 🔧 golang

Comments

@pconstantinou
Copy link

What do you want to change?

Background

sqlc currently allows queries to generate a struct based on all the columns of a table using the table name.* syntax.
This is useful but only satisfies a subset of use cases.

Problem

Many application scenarios use various formats for from and where clauses with the same columns in the result. For data-intensive applications where a large number of rows are returned, retrieving a subset of the columns is not just desirable but necessary.

A common use case is where the underlying table has a UUID-based user_id and the application wants varying subsets of the user's data. The table has a few other small columns where the application retrieves thousands of rows as a response.
The majority of the data (in bytes) returned will be the user_id repeated over and over again unnecessarily.

Further, the use cases where a variety of queries that all return the same row structure are common.

sqlc currently creates a unique Row struct whenever specific column names are given.

Workarounds and Issues with Go

I've experimented with extensions with limited success. Extending the structures generated from sqlc by implementing getters and a common interface does little to address the problem. While individual row structures can have a common interface. The slice of rows returned can't be cast to a slice of its interface. Reallocating the whole slice generates a large amount of garbage and allocations.

I'd hoped that the new iterator would provide a good workaround, but benchmarking shows that iterators returning interfaces to structures also generate a new memory allocation for each row record when the struct is cast on an interface.

An unattractive solution is to use the new iterator and return a new struct copying each field.

Proposal (very open to other options)

In the query.sql file, introduce a new keyword that functions like --name:. This could be --row: which would provide the name of the common struct. All queries with the same row: definition would use the same struct. The compiler would generate an error if the struct defined by the row was not compatible (ie. contained the same columns with the same types).

sqlc's strength is the ability to identify query and data structure errors at compile time. That spirit should continue, so "compatibility" should be interpreted strictly. Returning a subset of the row's columns should not be considered compatible.

I recommend allowing the same row struct to be used on different tables provided that the data structures are compatible. This will allow a semblance of data polymorphism.

This approach would not allow embedding row structs in other structs but would allow the existing table embedding.

What database engines need to be changed?

No response

What programming language backends need to be changed?

Go

@pconstantinou pconstantinou added the enhancement New feature or request label Sep 10, 2024
@dosubot dosubot bot added the 🔧 golang label Sep 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request 🔧 golang
Projects
None yet
Development

No branches or pull requests

1 participant