Skip to content

Commit e12ada6

Browse files
[Schema Management] Ignore index changes when comparing schemas (#337)
1 parent b46c6ac commit e12ada6

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

src/main/scala/models/schemas/ArcaneSchema.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ trait ArcaneSchemaField:
3939
val name: String
4040
val fieldType: ArcaneType
4141

42+
/** Field comparison that ignored field indexes. Needed to prevent reordering from triggering schema changes.
43+
* @return
44+
*/
45+
final def identical(other: ArcaneSchemaField): Boolean =
46+
other.name.toLowerCase() == name.toLowerCase() && other.fieldType == fieldType
47+
4248
/** A field in the schema definition that carries index information from the source that can be re-applied when
4349
* converting to Iceberg
4450
*/
@@ -132,11 +138,11 @@ object ArcaneSchema:
132138
*/
133139
extension (targetSchema: ArcaneSchema)
134140
def getMissingFields(sourceSchema: ArcaneSchema): Seq[ArcaneSchemaField] =
135-
sourceSchema.filter { sourceField => !targetSchema.contains(sourceField) }
141+
sourceSchema.filter { sourceField => !targetSchema.exists(_.identical(sourceField)) }
136142

137143
extension (targetSchema: ArcaneSchema)
138144
def getMissingFields(sourceFields: Seq[ArcaneSchemaField]): Seq[ArcaneSchemaField] =
139-
sourceFields.filter { sourceField => !targetSchema.contains(sourceField) }
145+
sourceFields.filter { sourceField => !targetSchema.exists(_.identical(sourceField)) }
140146

141147
given NamedCell[ArcaneSchemaField] with
142148
extension (field: ArcaneSchemaField) def name: String = field.name

src/test/scala/tests/models/ArcaneSchemaTests.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.sneaksanddata.arcane.framework
22
package tests.models
33

44
import models.schemas.ArcaneType.{BigDecimalType, IntType, ListType, StringType}
5-
import models.schemas.{ArcaneSchema, IndexedField, MergeKeyField}
5+
import models.schemas.{ArcaneSchema, IndexedField, IndexedMergeKeyField, MergeKeyField}
66

77
import org.scalatest.Inspectors.forAll
88
import org.scalatest.flatspec.AnyFlatSpec
@@ -41,6 +41,20 @@ class ArcaneSchemaTests extends AnyFlatSpec with Matchers {
4141
ArcaneSchema(Seq(MergeKeyField)),
4242
ArcaneSchema(Seq(IndexedField("colA", StringType, 1), IndexedField("colB", IntType, 2))),
4343
Seq(MergeKeyField)
44+
),
45+
(
46+
ArcaneSchema(Seq(IndexedMergeKeyField(0), IndexedField("colA", StringType, 1))),
47+
ArcaneSchema(
48+
Seq(IndexedMergeKeyField(1), IndexedField("colA", StringType, 2), IndexedField("colB", IntType, 3))
49+
),
50+
Seq()
51+
),
52+
(
53+
ArcaneSchema(
54+
Seq(IndexedMergeKeyField(1), IndexedField("colA", StringType, 2), IndexedField("colB", IntType, 3))
55+
),
56+
ArcaneSchema(Seq(IndexedMergeKeyField(0), IndexedField("colA", StringType, 1))),
57+
Seq(IndexedField("colB", IntType, 3))
4458
)
4559
)
4660
) { case (schemaA, schemaB, expected) =>

0 commit comments

Comments
 (0)