Skip to content

Commit e2ee02e

Browse files
Quote foreign key constraint names to support numeric table prefixes (#670)
* Initial plan * Temporary: Set target framework to net8.0 for development Co-authored-by: sebastienros <[email protected]> * Fix: Quote foreign key constraint names to support numeric prefixes Co-authored-by: sebastienros <[email protected]> * Revert temporary TFM changes, restore net8.0;net10.0 targets Co-authored-by: sebastienros <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: sebastienros <[email protected]>
1 parent 579c21f commit e2ee02e

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

src/YesSql.Core/Provider/BaseDialect.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public virtual string GetAddForeignKeyConstraintString(string name, string[] src
136136
}
137137

138138
res.Append(" constraint ")
139-
.Append(name)
139+
.Append(QuoteForColumnName(name))
140140
.Append(" foreign key (")
141141
.AppendJoin(", ", srcColumns)
142142
.Append(") references ")
@@ -154,7 +154,7 @@ public virtual string GetAddForeignKeyConstraintString(string name, string[] src
154154

155155
public virtual string GetDropForeignKeyConstraintString(string name)
156156
{
157-
return " drop constraint " + name;
157+
return " drop constraint " + QuoteForColumnName(name);
158158
}
159159

160160
public virtual bool SupportsIfExistsBeforeTableName => false;

src/YesSql.Provider.MySql/MySqlDialect.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public override string FormatIndexName(string name)
191191

192192
public override string GetDropForeignKeyConstraintString(string name)
193193
{
194-
return " drop foreign key " + FormatKeyName(name);
194+
return " drop foreign key " + QuoteForColumnName(FormatKeyName(name));
195195
}
196196

197197
public override string GetAddForeignKeyConstraintString(string name, string[] srcColumns, string destQuotedTable, string[] destColumns, bool primaryKey)

src/YesSql.Provider.PostgreSql/PostgreSqlDialect.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public override string FormatIndexName(string name)
182182
}
183183
public override string GetDropForeignKeyConstraintString(string name)
184184
{
185-
return " drop foreign key " + name;
185+
return " drop constraint " + QuoteForColumnName(name);
186186
}
187187

188188
public override string DefaultValuesInsert => "DEFAULT VALUES";

test/YesSql.Tests/PostgreSqlTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,42 @@ await builder.CreateReduceIndexTableAsync<PersonsByNameCol>(column => column
118118
await transaction.CommitAsync();
119119
}
120120
}
121+
122+
[Fact]
123+
public async Task ShouldQuoteForeignKeyConstraintsWithNumericPrefix()
124+
{
125+
// Test that foreign key constraints are properly quoted when table prefix starts with a digit
126+
// This addresses: https://github.com/sebastienros/yessql/issues/XXX
127+
var numericPrefixConfig = new Configuration()
128+
.UsePostgreSql(ConnectionStringBuilder.ConnectionString, "BabyYoda")
129+
.SetTablePrefix("1abcd_") // Prefix starting with a digit
130+
.UseBlockIdGenerator()
131+
.SetIdentityColumnSize(IdentityColumnSize.Int64);
132+
133+
using var store = await StoreFactory.CreateAndInitializeAsync(numericPrefixConfig);
134+
135+
await using var connection = store.Configuration.ConnectionFactory.CreateConnection();
136+
await connection.OpenAsync();
137+
138+
await using (var transaction = await connection.BeginTransactionAsync(store.Configuration.IsolationLevel))
139+
{
140+
var builder = new SchemaBuilder(store.Configuration, transaction);
141+
142+
// This should not throw even with a numeric prefix
143+
await builder.CreateMapIndexTableAsync<PersonByName>(column => column
144+
.Column<string>(nameof(PersonByName.SomeName))
145+
);
146+
147+
await transaction.CommitAsync();
148+
}
149+
150+
// Clean up
151+
await using (var transaction = await connection.BeginTransactionAsync(store.Configuration.IsolationLevel))
152+
{
153+
var builder = new SchemaBuilder(store.Configuration, transaction);
154+
await builder.DropMapIndexTableAsync<PersonByName>();
155+
await transaction.CommitAsync();
156+
}
157+
}
121158
}
122159
}

0 commit comments

Comments
 (0)