New KSP compiler module which processes @Selectable annotated data classes. I kept the KSP compiler more general, so if we ever want to add a new annotation, we can just use this module.
@Selectable
@Serializable
data class Movie(
val id: Int,
val name: String,
@ColumnName("created_at") //if the parameter names differs from the column name, add this annotation
val createdAt: Instant,
@Foreign //Mark a foreign relationship
@ColumnName("studio_id") //Either the table name or column name
val studio: Studio, //This should also be a `@Selectable` type
@ColumnName("metadata") //query JSON columns
@JsonPath("video", "resolution")
val resolution: String
)
Call the generated addSelectableTypes() method in the PostgrestConfig:
install(Postgrest) {
addSelectableTypes()
}
Use the new overloads for selecting:
val movies: List<Movie> = supabase.from("movies").select<Movie>().decodeList()
//or for insert, update, etc.:
//Note that `myNewMovie` is obviously a different type
val updatedMovie: Movie = supabase.from("movies").insert(myNewMovie) {
select<Movie>()
}
Design details
There are 6 annotations:
@Serializable - Data classes will be processed by the compiler and columns will be generated based of the constructor parameters.
@ColumnName - Used to specify the actual column name when the parameter name differs. For foreign columns, this can be either the column name or foreign table.
@JsonPath - Used to specify a Json Path to query a JSON column
@Foreign - Used for foreign columns so the compiler knows that it has to generate nested columns
@ApplyFunction - Used to apply an aggregate function
@Cast - Used to cast a column to a type. If no type is specified, then auto casting will be attempted (e.g. if the parameter type is a String then the column will be cast to a text)
Todo:
~[ ] Find a solution for spreading embedded resources~ - Will be unsupported for now
[x] Tests - To test the annotation processor, maybe use kotlin-compile-testing in the future
Implementation
There is a new Postgrest config property columnRegistry which stores column data under the full class name for annotated data classes. The KSP compiler fills this registry when the generated addSelectableTypes() method is called.
Example for the generated method [Not visible normally]:
/**
* Adds the types annotated with [Selectable] to the ColumnRegistry. Allows to use the automatically generated columns in the PostgrestQueryBuilder.
*
* This file is generated by the SelectableSymbolProcessor.
* Do not modify it manually.
*/
@OptIn(SupabaseInternal::class)
public fun Postgrest.Config.addSelectableTypes() {
columnRegistry.registerColumns("Movie", "id,name,createdAt:created_at,studio:studio_id(id,name),metadata->video->resolution")
columnRegistry.registerColumns("Studio", "id,name")
}
What kind of change does this PR introduce?
Feature
What is the new behavior?
New KSP compiler module which processes
@Selectable
annotated data classes. I kept the KSP compiler more general, so if we ever want to add a new annotation, we can just use this module.How it works
Add the KSP compiler
Annotate your data models with
@Selectable
:Call the generated
addSelectableTypes()
method in the PostgrestConfig:Use the new overloads for selecting:
Design details
There are 6 annotations:
@Serializable
- Data classes will be processed by the compiler and columns will be generated based of the constructor parameters.@ColumnName
- Used to specify the actual column name when the parameter name differs. For foreign columns, this can be either the column name or foreign table.@JsonPath
- Used to specify a Json Path to query a JSON column@Foreign
- Used for foreign columns so the compiler knows that it has to generate nested columns@ApplyFunction
- Used to apply an aggregate function@Cast
- Used to cast a column to a type. If no type is specified, then auto casting will be attempted (e.g. if the parameter type is aString
then the column will be cast to atext
)Todo:
kotlin-compile-testing
in the futureImplementation
There is a new Postgrest config property
columnRegistry
which stores column data under the full class name for annotated data classes. The KSP compiler fills this registry when the generatedaddSelectableTypes()
method is called. Example for the generated method [Not visible normally]:Additional context
See discussion in #761