Skip to content

Commit 93732cd

Browse files
committed
Add alias support for json columns
1 parent be8a919 commit 93732cd

File tree

5 files changed

+41
-14
lines changed

5 files changed

+41
-14
lines changed

KSP/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ dependencies {
1717

1818
tasks.named<KotlinCompilationTask<*>>("compileKotlin").configure {
1919
compilerOptions.freeCompilerArgs.add("-opt-in=io.github.jan.supabase.annotations.SupabaseInternal")
20+
compilerOptions.freeCompilerArgs.add("-opt-in=io.github.jan.supabase.annotations.SupabaseExperimental")
2021
}

KSP/src/main/kotlin/io/github/jan/supabase/ksp/ColumnOptions.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package io.github.jan.supabase.ksp
22

33
data class ColumnOptions(
44
val alias: String,
5-
val columnName: String,
5+
val columnName: String?,
66
val isForeign: Boolean,
77
val jsonPath: List<String>?,
88
val returnAsText: Boolean,
99
val function: String?,
1010
val cast: String?,
1111
val innerColumns: String,
12+
val jsonKey: String?
1213
)

KSP/src/main/kotlin/io/github/jan/supabase/ksp/SelectableSymbolProcessor.kt

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,11 @@ class SelectableSymbolProcessor(
9797
} else ""
9898
val alias = parameter.name!!.getShortName()
9999
val columnName = parameter.annotations.getAnnotationOrNull(ColumnName::class.java.simpleName)
100-
?.arguments?.getParameterValue<String>(ColumnName.NAME_PARAMETER_NAME) ?: alias
100+
?.arguments?.getParameterValue<String>(ColumnName.NAME_PARAMETER_NAME)
101101
val isForeign = parameter.annotations.getAnnotationOrNull(Foreign::class.java.simpleName) != null
102102
val jsonPathArguments = parameter.annotations.getAnnotationOrNull(JsonPath::class.java.simpleName)?.arguments
103103
val jsonPath = jsonPathArguments?.getParameterValue<ArrayList<String>>(JsonPath.PATH_PARAMETER_NAME)
104+
val jsonKey = jsonPathArguments?.getParameterValue<String>(JsonPath.KEY_PARAMETER_NAME)
104105
val returnAsText = jsonPathArguments?.getParameterValue<Boolean>(JsonPath.RETURN_AS_TEXT_PARAMETER_NAME) == true
105106
val function = parameter.annotations.getAnnotationOrNull(ApplyFunction::class.java.simpleName)
106107
?.arguments?.getParameterValue<String>(ApplyFunction.FUNCTION_PARAMETER_NAME)
@@ -111,6 +112,7 @@ class SelectableSymbolProcessor(
111112
columnName = columnName,
112113
isForeign = isForeign,
113114
jsonPath = jsonPath,
115+
jsonKey = jsonKey,
114116
returnAsText = returnAsText,
115117
function = function,
116118
cast = cast,
@@ -143,8 +145,8 @@ class SelectableSymbolProcessor(
143145
if(options.jsonPath != null && options.function != null) {
144146
logger.error("Parameter $parameterName can't have both @JsonPath and @ApplyFunction annotation", symbol)
145147
}
146-
if(options.jsonPath != null && options.jsonPath.isEmpty()) {
147-
logger.error("Parameter $parameterName can't have an empty @JsonPath annotation. At least two elements (the column name and a key) are required.", symbol)
148+
if(options.jsonKey != null && options.columnName == null) {
149+
logger.error("Parameter $parameterName must have a @ColumnName annotation when using @JsonPath", symbol)
148150
}
149151
}
150152

@@ -156,12 +158,15 @@ class SelectableSymbolProcessor(
156158
): String {
157159
return buildString {
158160
if(options.jsonPath != null) {
159-
append(buildJsonPath(options.jsonPath, options.returnAsText))
161+
if(options.alias != options.jsonKey) {
162+
append("${options.alias}:")
163+
}
164+
append(buildJsonPath(options.columnName, options.jsonKey, options.jsonPath, options.returnAsText))
160165
return@buildString
161166
}
162167

163-
//If the alias is the same as the column name, we can just assume parameter name (alias) is the column name
164-
if(options.alias == options.columnName) {
168+
//If the column name is not provided, use the alias (parameter name)
169+
if(options.columnName == null) {
165170
append(options.alias)
166171
} else {
167172
append("${options.alias}:${options.columnName}")
@@ -188,11 +193,23 @@ class SelectableSymbolProcessor(
188193
}
189194
}
190195

191-
private fun buildJsonPath(jsonPath: List<String>, returnAsText: Boolean): String {
196+
private fun buildJsonPath(
197+
columnName: String?,
198+
jsonKey: String?,
199+
jsonPath: List<String>,
200+
returnAsText: Boolean
201+
): String {
192202
val operator = if(returnAsText) "->>" else "->"
193-
val formattedPath = if(jsonPath.size > 1) jsonPath.dropLast(1).joinToString("->") else ""
194-
val key = jsonPath.last()
195-
return "$formattedPath$operator$key"
203+
return buildString {
204+
append(columnName)
205+
if(jsonPath.isNotEmpty()) {
206+
jsonPath.forEach {
207+
append("->$it")
208+
}
209+
}
210+
append(operator)
211+
append(jsonKey)
212+
}
196213
}
197214

198215
}

Postgrest/src/commonMain/kotlin/io/github/jan/supabase/postgrest/annotations/JsonPath.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,25 @@ import io.github.jan.supabase.annotations.SupabaseInternal
1414
* ```
1515
* ```kotlin
1616
* @Selectable
17-
* data class Example(@JsonPath("data", "id") val id: Int)
17+
* data class Example(
18+
* @ColumnName("data")
19+
* @JsonPath("id")
20+
* val id: Int
21+
* )
1822
* ```
1923
*
20-
* @param path The path to the JSON property. The first element of the array is always the column name.
24+
* @param key The key of the JSON property.
25+
* @param path Additional path to the JSON property. If the JSON property is nested, you can specify the path to the property.
2126
* @param returnAsText Whether to return the JSON property as text. If `true`, the JSON property will be returned as a string. If `false`, the JSON property will be returned as JSON.
2227
*
2328
*/
2429
@Target(AnnotationTarget.VALUE_PARAMETER)
2530
@Retention(AnnotationRetention.SOURCE)
26-
annotation class JsonPath(vararg val path: String, val returnAsText: Boolean = false) {
31+
annotation class JsonPath(val key: String, vararg val path: String, val returnAsText: Boolean = false) {
2732

2833
companion object {
2934
@SupabaseInternal const val PATH_PARAMETER_NAME = "path"
35+
@SupabaseInternal const val KEY_PARAMETER_NAME = "key"
3036
@SupabaseInternal const val RETURN_AS_TEXT_PARAMETER_NAME = "returnAsText"
3137
}
3238

Postgrest/src/commonMain/kotlin/io/github/jan/supabase/postgrest/annotations/Selectable.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.github.jan.supabase.postgrest.annotations
22

3+
import io.github.jan.supabase.annotations.SupabaseExperimental
34
import io.github.jan.supabase.postgrest.query.PostgrestQueryBuilder
45

56
/**
@@ -40,4 +41,5 @@ import io.github.jan.supabase.postgrest.query.PostgrestQueryBuilder
4041
*/
4142
@Target(AnnotationTarget.CLASS)
4243
@Retention(AnnotationRetention.SOURCE)
44+
@SupabaseExperimental
4345
annotation class Selectable

0 commit comments

Comments
 (0)