-
Notifications
You must be signed in to change notification settings - Fork 496
/
ExecuteQueryGenerator.kt
97 lines (88 loc) · 3.16 KB
/
ExecuteQueryGenerator.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package app.cash.sqldelight.core.compiler
import app.cash.sqldelight.core.capitalize
import app.cash.sqldelight.core.compiler.model.NamedExecute
import app.cash.sqldelight.core.compiler.model.NamedMutator
import app.cash.sqldelight.core.lang.argumentType
import app.cash.sqldelight.core.lang.psi.StmtIdentifierMixin
import app.cash.sqldelight.core.lang.util.TableNameElement
import app.cash.sqldelight.core.psi.SqlDelightStmtClojureStmtList
import com.alecstrong.sql.psi.core.psi.SqlDeleteStmtLimited
import com.alecstrong.sql.psi.core.psi.SqlInsertStmt
import com.alecstrong.sql.psi.core.psi.SqlUpdateStmtLimited
import com.intellij.psi.util.PsiTreeUtil
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.KModifier.SUSPEND
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.PropertySpec
open class ExecuteQueryGenerator(
private val query: NamedExecute,
) : QueryGenerator(query) {
internal open fun tablesUpdated(): List<TableNameElement> {
if (query.statement is SqlDelightStmtClojureStmtList) {
return PsiTreeUtil.findChildrenOfAnyType(
query.statement,
SqlUpdateStmtLimited::class.java,
SqlDeleteStmtLimited::class.java,
SqlInsertStmt::class.java,
).flatMap {
MutatorQueryGenerator(
when (it) {
is SqlUpdateStmtLimited -> NamedMutator.Update(it, query.identifier as StmtIdentifierMixin)
is SqlDeleteStmtLimited -> NamedMutator.Delete(it, query.identifier as StmtIdentifierMixin)
is SqlInsertStmt -> NamedMutator.Insert(it, query.identifier as StmtIdentifierMixin)
else -> throw IllegalArgumentException("Unexpected statement $it")
},
).tablesUpdated()
}.distinctBy { it.name }
}
return emptyList()
}
private fun FunSpec.Builder.notifyQueries(): FunSpec.Builder {
val tablesUpdated = tablesUpdated()
if (tablesUpdated.isEmpty()) return this
// The list of affected tables:
// notifyQueries { emit ->
// emit("players")
// emit("teams")
// }
addCode(
CodeBlock.builder()
.beginControlFlow("notifyQueries(%L) { emit ->", query.id)
.apply {
tablesUpdated.sortedBy { it.name }.forEach {
addStatement("emit(\"${it.name}\")")
}
}
.endControlFlow()
.build(),
)
return this
}
/**
* The public api to execute [query]
*/
fun function(): FunSpec {
return interfaceFunction()
.addCode(executeBlock())
.notifyQueries()
.build()
}
fun interfaceFunction(): FunSpec.Builder {
return FunSpec.builder(query.name)
.apply { if (generateAsync) addModifiers(SUSPEND) }
.also(this::addJavadoc)
.addParameters(
query.parameters.map {
ParameterSpec.builder(it.name, it.argumentType()).build()
},
)
}
fun value(): PropertySpec {
return PropertySpec.builder(query.name, ClassName("", query.name.capitalize()), KModifier.PRIVATE)
.initializer("${query.name.capitalize()}()")
.build()
}
}