feat(persistence): extend SqlWriter

This commit is contained in:
dualfroz committed 2026-09-02 19:31:11 +02:00
1 parent 364dd2e564
commit 349b06d470
1 file changed
+38
@@ -445,6 +445,44 @@ object SqlWriter {
is BinaryExpression ->
"(${expression(expression.left)} ${expression.operator.symbol} ${expression(expression.right)})"
is UnaryExpression -> "(${expression.operator.symbol} ${expression(expression.operand)})"
is CallExpression -> "${expression.name}(${expression.arguments.joinToString(", ") { expression(it) }})"
is IsNullExpression ->
"(${expression(expression.operand)} IS ${if (expression.negated) "NOT " else ""}NULL)"
is InExpression ->
"(${expression(expression.operand)} ${if (expression.negated) "NOT " else ""}IN (${expression.values.joinToString(", ") { expression(it) }}))"
is BetweenExpression ->
"(${expression(expression.operand)} ${if (expression.negated) "NOT " else ""}BETWEEN ${expression(expression.low)} AND ${expression(expression.high)})"
is LikeExpression ->
"(${expression(expression.operand)} ${if (expression.negated) "NOT " else ""}LIKE ${expression(expression.pattern)})"
is CaseExpression -> buildString {
append("CASE ")
expression.operand?.let { append(expression(it)); append(' ') }
expression.branches.forEach { append("WHEN ${expression(it.condition)} THEN ${expression(it.result)} ") }
expression.elseExpression?.let { append("ELSE ${expression(it)} ") }
append("END")
}
is ScalarSubqueryExpression -> "(${selectText(expression.select)})"
is ExistsExpression -> "EXISTS (${selectText(expression.select)})"
is InSubqueryExpression ->
"(${expression(expression.operand)} ${if (expression.negated) "NOT " else ""}IN (${selectText(expression.select)}))"
is CastExpression ->
"CAST(${expression(expression.operand)} AS ${expression.targetType.displayWith(expression.precision, expression.scale)})"
is CollateExpression -> "(${expression(expression.operand)} COLLATE ${expression.collation.sqlName})"
is WindowExpression -> "${expression.name}(${windowArgumentsText(expression)}) OVER (${overClauseText(expression)})"
is NextValueExpression -> "NEXTVAL(${literal(Value.TextValue(expression.sequenceName))})"
is CurrentValueExpression -> "CURRVAL(${literal(Value.TextValue(expression.sequenceName))})"
// Unreachable in practice: writeMerge never emits statement.returning at all (RETURNING is
// dropped from every persisted DML statement - see writeInsert/writeUpdate/writeDelete's own
// callers), so MERGE_ACTION() - only ever legal inside a MERGE's RETURNING - never reaches
// this writer. Kept here only to keep `when` exhaustive.
is MergeActionExpression -> "MERGE_ACTION()"
// Never actually reaches here in practice - canPersist excludes PREPARE/EXECUTE/DEALLOCATE
// outright (see its own doc), and resolveExecute always substitutes every ParameterExpression
// for a literal before the concrete INSERT/UPDATE/DELETE/SELECT it resolved to is ever handed
// to this writer. Kept only so `when` stays exhaustive, and so a `$1` typed directly into a
// persistable statement outside PREPARE (structurally legal, just meaningless - Evaluator
// throws on it) still round-trips its own text faithfully rather than being silently mangled.
is ParameterExpression -> "\$${expression.index}"
}
private fun literal(value: Value): String = when (value) {