diff --git a/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt b/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt
index 82ad726d..ca184a06 100644
--- a/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt
+++ b/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt
@@ -4,5 +4,20 @@ import kotlinx.serialization.Serializable
@Serializable
public data class Schema(val tables: List
) {
+ init {
+ validate()
+ }
+
public constructor(vararg tables: Table) : this(tables.asList())
+
+
+ public fun validate() {
+ val tableNames = mutableSetOf()
+ tables.forEach { table ->
+ if (!tableNames.add(table.name)) {
+ throw AssertionError("Duplicate table name: ${table.name}")
+ }
+ table.validate()
+ }
+ }
}
\ No newline at end of file
diff --git a/core/src/commonTest/kotlin/com/powersync/db/schema/SchemaTest.kt b/core/src/commonTest/kotlin/com/powersync/db/schema/SchemaTest.kt
new file mode 100644
index 00000000..0c4d3ec7
--- /dev/null
+++ b/core/src/commonTest/kotlin/com/powersync/db/schema/SchemaTest.kt
@@ -0,0 +1,40 @@
+package com.powersync.db.schema
+
+import kotlin.test.*
+
+class SchemaTest {
+
+ @Test
+ fun schemaConstructionWithValidTablesShouldSucceed() {
+ val table1 = Table("table1", listOf(Column("column1", ColumnType.TEXT)))
+ val table2 = Table("table2", listOf(Column("column2", ColumnType.INTEGER)))
+
+ val schema = Schema(table1, table2)
+
+ assertEquals(2, schema.tables.size)
+ assertEquals("table1", schema.tables[0].name)
+ assertEquals("table2", schema.tables[1].name)
+ }
+
+ @Test
+ fun schemaConstructionWithInvalidTableShouldThrowException() {
+ val validTable = Table("validTable", listOf(Column("column1", ColumnType.TEXT)))
+ val invalidTable = Table("#invalid-table", listOf(Column("column1", ColumnType.TEXT)))
+
+ val exception = assertFailsWith {
+ Schema(validTable, invalidTable)
+ }
+ assertEquals(exception.message, "Invalid characters in table name: #invalid-table")
+ }
+
+ @Test
+ fun schemaShouldDetectDuplicateTableNames() {
+ val table1 = Table("table1", listOf(Column("column1", ColumnType.TEXT)))
+ val table2 = Table("table1", listOf(Column("column2", ColumnType.INTEGER)))
+
+ val exception = assertFailsWith {
+ Schema(table1, table2)
+ }
+ assertEquals(exception.message, "Duplicate table name: table1")
+ }
+}
\ No newline at end of file
diff --git a/core/src/commonTest/kotlin/com/powersync/db/schema/TableTest.kt b/core/src/commonTest/kotlin/com/powersync/db/schema/TableTest.kt
index d5f03894..0fa0c16f 100644
--- a/core/src/commonTest/kotlin/com/powersync/db/schema/TableTest.kt
+++ b/core/src/commonTest/kotlin/com/powersync/db/schema/TableTest.kt
@@ -154,4 +154,17 @@ class TableTest {
assertEquals(exception.message,"Duplicate index users.name_index")
}
+
+
+ @Test
+ fun testValidationOfIdColumn() {
+ val columns = listOf(Column("id", ColumnType.TEXT))
+ val table = Table("users", columns)
+
+ val exception = assertFailsWith {
+ table.validate()
+ }
+
+ assertEquals(exception.message,"users: id column is automatically added, custom id columns are not supported")
+ }
}
\ No newline at end of file