diff --git a/Directory.Packages.props b/Directory.Packages.props
index c2742e6..cc94025 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -7,7 +7,7 @@
-
+
diff --git a/src/NSchema.Postgres/NSchema.Postgres.csproj b/src/NSchema.Postgres/NSchema.Postgres.csproj
index b019ac7..4bff55c 100644
--- a/src/NSchema.Postgres/NSchema.Postgres.csproj
+++ b/src/NSchema.Postgres/NSchema.Postgres.csproj
@@ -20,7 +20,7 @@
true
true
snupkg
- 3.0.0-alpha.12
+ 3.0.0-beta.1
$(Version.Split('-')[0])
$(Version.Split('-')[0])
true
diff --git a/src/NSchema.Postgres/Sql/PostgresSchemaProvider.cs b/src/NSchema.Postgres/Sql/PostgresSchemaProvider.cs
index 3d0b3f4..37625d0 100644
--- a/src/NSchema.Postgres/Sql/PostgresSchemaProvider.cs
+++ b/src/NSchema.Postgres/Sql/PostgresSchemaProvider.cs
@@ -132,10 +132,10 @@ private static async Task> QueryColumns(NpgsqlConnection conn, s
seq.seqincrement AS identity_increment,
CASE WHEN c.is_generated = 'ALWAYS' THEN c.generation_expression END AS generation_expression
FROM information_schema.columns c
+ LEFT JOIN pg_namespace n ON n.nspname = c.table_schema
LEFT JOIN pg_class t ON t.relname = c.table_name
+ AND t.relnamespace = n.oid
AND t.relkind = 'r'
- LEFT JOIN pg_namespace n ON n.oid = t.relnamespace
- AND n.nspname = c.table_schema
LEFT JOIN pg_attribute a ON a.attrelid = t.oid
AND a.attname = c.column_name
LEFT JOIN pg_depend d ON d.refobjid = t.oid
diff --git a/tests/NSchema.Postgres.Tests/Sql/PostgresSchemaProviderTests.cs b/tests/NSchema.Postgres.Tests/Sql/PostgresSchemaProviderTests.cs
index 7d4c5aa..dec3769 100644
--- a/tests/NSchema.Postgres.Tests/Sql/PostgresSchemaProviderTests.cs
+++ b/tests/NSchema.Postgres.Tests/Sql/PostgresSchemaProviderTests.cs
@@ -1042,4 +1042,45 @@ public async Task GetSchema_Extensions_AreReportedAtRootWithVersion()
citext.Version.ShouldNotBeNull();
schema.Extensions.ShouldNotContain(e => e.Name == "plpgsql");
}
+
+ // ── Same table name across schemas ────────────────────────────────────────
+
+ // Regression: the columns query joined pg_class on relname alone (not namespace), so a table name shared by
+ // two schemas matched both pg_class rows and fanned every column row out once per schema — columns appeared
+ // duplicated in each table. Each table must report only its own columns.
+ [Fact]
+ public async Task GetSchema_SameTableNameInDifferentSchemas_DoesNotDuplicateColumns()
+ {
+ // Arrange
+ var other = $"test_{Guid.NewGuid():N}";
+ await Exec($"CREATE SCHEMA \"{other}\"");
+ try
+ {
+ await Exec($"""
+ CREATE TABLE "{_schema}".users (
+ id INTEGER NOT NULL,
+ name TEXT NOT NULL
+ )
+ """);
+ await Exec($"""
+ CREATE TABLE "{other}".users (
+ code INTEGER NOT NULL,
+ region TEXT NOT NULL
+ )
+ """);
+
+ // Act
+ var model = await _sut.GetSchema([_schema, other], TestContext.Current.CancellationToken);
+
+ // Assert
+ var primary = model.Schemas.Single(s => s.Name == _schema).Tables.Single(t => t.Name == "users");
+ var secondary = model.Schemas.Single(s => s.Name == other).Tables.Single(t => t.Name == "users");
+ primary.Columns.Select(c => c.Name).ShouldBe(["id", "name"]);
+ secondary.Columns.Select(c => c.Name).ShouldBe(["code", "region"]);
+ }
+ finally
+ {
+ await Exec($"DROP SCHEMA IF EXISTS \"{other}\" CASCADE");
+ }
+ }
}