@@ -10,6 +10,8 @@ import me.liuwj.ktorm.schema.*
1010 */
1111@Suppress(" UNCHECKED_CAST" )
1212fun <E : Entity <E >> Table<E>.add (entity : E ): Int {
13+ entity.implementation.checkUnexpectedDiscarding(this )
14+
1315 val assignments = findInsertColumns(entity).takeIf { it.isNotEmpty() } ? : return 0
1416
1517 val expression = AliasRemover .visit(
@@ -66,6 +68,8 @@ private fun Table<*>.findInsertColumns(entity: Entity<*>): Map<Column<*>, Any?>
6668@Suppress(" UNCHECKED_CAST" )
6769internal fun EntityImplementation.doFlushChanges (): Int {
6870 val fromTable = this .fromTable?.takeIf { this .parent == null } ? : error(" The entity is not associated with any table yet." )
71+ checkUnexpectedDiscarding(fromTable)
72+
6973 val primaryKey = fromTable.primaryKey ? : error(" Table ${fromTable.tableName} doesn't have a primary key." )
7074 val assignments = findChangedColumns(fromTable).takeIf { it.isNotEmpty() } ? : return 0
7175
@@ -111,26 +115,17 @@ private fun EntityImplementation.findChangedColumns(fromTable: Table<*>): Map<Co
111115 var anyChanged = false
112116 var curr: Any? = this
113117
114- for ((i, prop) in binding.properties.withIndex() ) {
118+ for (prop in binding.properties) {
115119 if (curr is Entity <* >) {
116120 curr = curr.implementation
117121 }
118122
119123 check(curr is EntityImplementation ? )
120124
121- val changed = if (curr == null ) false else prop.name in curr.changedProperties
122-
123- // Add check to avoid bug #10
124- if (changed && i > 0 ) {
125- check(curr != null )
126-
127- if (curr.fromTable != null && curr.getRoot() != this ) {
128- val propPath = binding.properties.subList(0 , i + 1 ).joinToString(separator = " ." , prefix = " this." ) { it.name }
129- throw IllegalStateException (" $propPath may be unexpectedly discarded after flushChanges, please save it to database first." )
130- }
125+ if (curr != null && prop.name in curr.changedProperties) {
126+ anyChanged = true
131127 }
132128
133- anyChanged = anyChanged || changed
134129 curr = curr?.getProperty(prop.name)
135130 }
136131
@@ -144,15 +139,6 @@ private fun EntityImplementation.findChangedColumns(fromTable: Table<*>): Map<Co
144139 return assignments
145140}
146141
147- private tailrec fun EntityImplementation.getRoot (): EntityImplementation {
148- val parent = this .parent
149- if (parent == null ) {
150- return this
151- } else {
152- return parent.getRoot()
153- }
154- }
155-
156142internal fun EntityImplementation.doDiscardChanges () {
157143 val fromTable = this .fromTable?.takeIf { this .parent == null } ? : error(" The entity is not associated with any table yet." )
158144
@@ -183,6 +169,54 @@ internal fun EntityImplementation.doDiscardChanges() {
183169 }
184170}
185171
172+ // Add check to avoid bug #10
173+ private fun EntityImplementation.checkUnexpectedDiscarding (fromTable : Table <* >) {
174+ for (column in fromTable.columns) {
175+ val binding = column.binding?.takeIf { column is SimpleColumn } ? : continue
176+
177+ if (binding is NestedBinding ) {
178+ var curr: Any? = this
179+
180+ for ((i, prop) in binding.properties.withIndex()) {
181+ if (curr == null ) {
182+ break
183+ }
184+ if (curr is Entity <* >) {
185+ curr = curr.implementation
186+ }
187+
188+ check(curr is EntityImplementation )
189+
190+ if (i > 0 && prop.name in curr.changedProperties && curr.fromTable != null && curr.getRoot() != this ) {
191+ val propPath = binding.properties.subList(0 , i + 1 ).joinToString(separator = " ." , prefix = " this." ) { it.name }
192+ throw IllegalStateException (" $propPath may be unexpectedly discarded, please save it to database first." )
193+ }
194+
195+ curr = curr.getProperty(prop.name)
196+ }
197+ }
198+ }
199+ }
200+
201+ private tailrec fun EntityImplementation.getRoot (): EntityImplementation {
202+ val parent = this .parent
203+ if (parent == null ) {
204+ return this
205+ } else {
206+ return parent.getRoot()
207+ }
208+ }
209+
210+ internal fun Entity <* >.clearChangesRecursively () {
211+ implementation.changedProperties.clear()
212+
213+ for ((_, value) in properties) {
214+ if (value is Entity <* >) {
215+ value.clearChangesRecursively()
216+ }
217+ }
218+ }
219+
186220@Suppress(" UNCHECKED_CAST" )
187221internal fun EntityImplementation.doDelete (): Int {
188222 val fromTable = this .fromTable?.takeIf { this .parent == null } ? : error(" The entity is not associated with any table yet." )
0 commit comments