@@ -24,17 +24,20 @@ import org.ktorm.dsl.AliasRemover
2424import org.ktorm.entity.EntitySequence
2525import org.ktorm.expression.ColumnAssignmentExpression
2626import org.ktorm.expression.UpdateExpression
27- import org.ktorm.ksp.compiler.util.*
27+ import org.ktorm.ksp.compiler.util._type
2828import org.ktorm.ksp.spi.TableMetadata
29- import org.ktorm.schema.Column
3029
3130@OptIn(KotlinPoetKspPreview ::class )
3231internal object UpdateFunctionGenerator {
3332
3433 fun generate (table : TableMetadata ): FunSpec {
35- val kdoc = " " +
36- " Update the given entity to the database and return the affected record number. " +
37- " If [isDynamic] is set to true, the generated SQL will include only the non-null columns. "
34+ val kdoc = """
35+ Update the given entity to the database.
36+
37+ @param entity the entity to be updated.
38+ @param isDynamic whether only non-null columns should be updated.
39+ @return the affected record number.
40+ """ .trimIndent()
3841
3942 val entityClass = table.entityClass.toClassName()
4043 val tableClass = ClassName (table.entityClass.packageName.asString(), table.tableClassName)
@@ -46,28 +49,13 @@ internal object UpdateFunctionGenerator {
4649 .addParameter(ParameterSpec .builder(" isDynamic" , typeNameOf<Boolean >()).defaultValue(" false" ).build())
4750 .returns(Int ::class .asClassName())
4851 .addCode(AddFunctionGenerator .checkForDml())
49- .addCode(addValFun())
52+ .addCode(AddFunctionGenerator . addValFun(table, useGeneratedKey = false ))
5053 .addCode(addAssignments(table))
51- .addCode(buildConditions(table))
52- .addCode(createExpression())
54+ .addCode(createExpression(table))
5355 .addStatement(" return database.executeUpdate(expression)" )
5456 .build()
5557 }
5658
57- private fun addValFun (): CodeBlock {
58- val code = """
59- fun <T : Any> MutableList<%1T<*>>.addVal(column: %2T<T>, value: T?, isDynamic: Boolean) {
60- if (!isDynamic || value != null) {
61- this += %1T(column.asExpression(), column.wrapArgument(value))
62- }
63- }
64-
65-
66- """ .trimIndent()
67-
68- return CodeBlock .of(code, ColumnAssignmentExpression ::class .asClassName(), Column ::class .asClassName())
69- }
70-
7159 private fun addAssignments (table : TableMetadata ): CodeBlock {
7260 return buildCodeBlock {
7361 addStatement(" val assignments = ArrayList<%T<*>>()" , ColumnAssignmentExpression ::class .asClassName())
@@ -78,14 +66,12 @@ internal object UpdateFunctionGenerator {
7866 }
7967
8068 addStatement(
81- " assignments.addVal(sourceTable.%N, entity.%N, isDynamic )" ,
69+ " assignments.addVal(sourceTable.%N, entity.%N)" ,
8270 column.columnPropertyName,
83- column.entityProperty.simpleName.asString(),
71+ column.entityProperty.simpleName.asString()
8472 )
8573 }
8674
87- add(" \n " )
88-
8975 beginControlFlow(" if (assignments.isEmpty())" )
9076 addStatement(" return 0" )
9177 endControlFlow()
@@ -94,20 +80,22 @@ internal object UpdateFunctionGenerator {
9480 }
9581 }
9682
97- private fun buildConditions (table : TableMetadata ): CodeBlock {
83+ private fun createExpression (table : TableMetadata ): CodeBlock {
9884 return buildCodeBlock {
99- add(" «val conditions = listOf(" )
85+ addStatement(
86+ " val visitor = database.dialect.createExpressionVisitor(%T)" ,
87+ AliasRemover ::class .asClassName()
88+ )
10089
101- for (column in table.columns) {
102- if (! column.isPrimaryKey) {
103- continue
104- }
90+ add(" «val conditions = " )
10591
92+ val primaryKeys = table.columns.filter { it.isPrimaryKey }
93+ for ((i, column) in primaryKeys.withIndex()) {
10694 val condition: String
10795 if (column.entityProperty._type .isMarkedNullable) {
108- condition = " sourceTable.%N·%M·entity.%N!!, "
96+ condition = " ( sourceTable.%N·%M·entity.%N!!) "
10997 } else {
110- condition = " sourceTable.%N·%M·entity.%N, "
98+ condition = " ( sourceTable.%N·%M·entity.%N) "
11199 }
112100
113101 add(
@@ -116,26 +104,18 @@ internal object UpdateFunctionGenerator {
116104 MemberName (" org.ktorm.dsl" , " eq" , true ),
117105 column.entityProperty.simpleName.asString()
118106 )
107+
108+ if (i < primaryKeys.lastIndex) {
109+ add(" ·%M·" , MemberName (" org.ktorm.dsl" , " and" , true ))
110+ }
119111 }
120112
121- add(" )\n »" )
122- }
123- }
113+ add(" \n »" )
124114
125- private fun createExpression (): CodeBlock {
126- val code = """
127- val expression = database.dialect.createExpressionVisitor(%T).visit(
128- %T(sourceTable.asExpression(), assignments, conditions.%M().asExpression())
115+ addStatement(
116+ " val expression = visitor.visit(%T(sourceTable.asExpression(), assignments, conditions))" ,
117+ UpdateExpression ::class .asClassName()
129118 )
130-
131-
132- """ .trimIndent()
133-
134- return CodeBlock .of(
135- code,
136- AliasRemover ::class .asClassName(),
137- UpdateExpression ::class .asClassName(),
138- MemberName (" org.ktorm.dsl" , " combineConditions" , true )
139- )
119+ }
140120 }
141121}
0 commit comments