Fix invalid CertificateCheckUrl column errors on existing databases.

Auto-migrate SonicContainer schema on startup, rename legacy typo columns, and use fallback SQL when the column is not yet present.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 13:24:20 +02:00
co-authored by Cursor
parent 76e280d809
commit 0a449727ad
5 changed files with 362 additions and 36 deletions
@@ -878,7 +878,7 @@ public sealed class SonicSetupRepository
nameof(environmentCode));
}
const string sql = """
const string sqlWithCheckUrl = """
SELECT
container.[SonicContainerId],
container.[SonicConnectionId],
@@ -913,6 +913,40 @@ public sealed class SonicSetupRepository
container.[ContainerName];
""";
const string sqlWithoutCheckUrl = """
SELECT
container.[SonicContainerId],
container.[SonicConnectionId],
container.[CompanyId],
container.[ContainerName],
container.[ContainerDisplayName],
container.[RestartTimeoutSeconds],
company.[CompanyCode],
connection.[ConnectionName]
FROM [dbo].[SonicContainer] AS container
INNER JOIN [dbo].[Company] AS company
ON company.[CompanyId] = container.[CompanyId]
INNER JOIN [dbo].[SonicConnection] AS connection
ON connection.[SonicConnectionId] =
container.[SonicConnectionId]
INNER JOIN [dbo].[Environment] AS environment
ON environment.[EnvironmentId] =
connection.[EnvironmentId]
WHERE container.[IsActive] = 1
AND company.[IsActive] = 1
AND connection.[IsActive] = 1
AND environment.[IsActive] = 1
AND environment.[EnvironmentCode] = @EnvironmentCode
AND
(
@SonicConnectionId IS NULL
OR container.[SonicConnectionId] = @SonicConnectionId
)
ORDER BY
company.[CompanyCode],
container.[ContainerName];
""";
List<ContainerOption> containers = [];
await using SqlConnection connection =
@@ -920,6 +954,15 @@ public sealed class SonicSetupRepository
await connection.OpenAsync(cancellationToken);
bool hasCertificateCheckUrl =
await DatabaseSchemaPatcher.HasCertificateCheckUrlColumnAsync(
_connectionString,
cancellationToken);
string sql = hasCertificateCheckUrl
? sqlWithCheckUrl
: sqlWithoutCheckUrl;
await using SqlCommand command =
new(sql, connection);
@@ -952,8 +995,9 @@ public sealed class SonicSetupRepository
int displayOrdinal =
reader.GetOrdinal("ContainerDisplayName");
int checkUrlOrdinal =
reader.GetOrdinal("CertificateCheckUrl");
int? checkUrlOrdinal = hasCertificateCheckUrl
? reader.GetOrdinal("CertificateCheckUrl")
: null;
containers.Add(
new ContainerOption
@@ -980,9 +1024,10 @@ public sealed class SonicSetupRepository
: reader.GetString(displayOrdinal),
CertificateCheckUrl =
reader.IsDBNull(checkUrlOrdinal)
? null
: reader.GetString(checkUrlOrdinal),
checkUrlOrdinal is int urlOrdinal
&& !reader.IsDBNull(urlOrdinal)
? reader.GetString(urlOrdinal)
: null,
RestartTimeoutSeconds =
reader.GetInt32(
@@ -1328,7 +1373,13 @@ public sealed class SonicSetupRepository
string? checkUrl =
TlsEndpointProbeService.NormalizeCheckUrl(certificateCheckUrl);
const string sql = """
bool hasCertificateCheckUrl =
await DatabaseSchemaPatcher.HasCertificateCheckUrlColumnAsync(
_connectionString,
cancellationToken);
string sql = hasCertificateCheckUrl
? """
INSERT INTO [dbo].[SonicContainer]
(
[CompanyId],
@@ -1354,6 +1405,31 @@ public sealed class SonicSetupRepository
SYSUTCDATETIME(),
SUSER_SNAME()
);
"""
: """
INSERT INTO [dbo].[SonicContainer]
(
[CompanyId],
[SonicConnectionId],
[ContainerName],
[ContainerDisplayName],
[RestartTimeoutSeconds],
[IsActive],
[CreationDateTime],
[CreatedBy]
)
OUTPUT INSERTED.[SonicContainerId]
VALUES
(
@CompanyId,
@SonicConnectionId,
@ContainerName,
@ContainerDisplayName,
@RestartTimeoutSeconds,
1,
SYSUTCDATETIME(),
SUSER_SNAME()
);
""";
await using SqlConnection connection =
@@ -1396,16 +1472,19 @@ public sealed class SonicSetupRepository
: display
});
command.Parameters.Add(
new SqlParameter(
"@CertificateCheckUrl",
SqlDbType.NVarChar,
500)
{
Value = checkUrl is null
? DBNull.Value
: checkUrl
});
if (hasCertificateCheckUrl)
{
command.Parameters.Add(
new SqlParameter(
"@CertificateCheckUrl",
SqlDbType.NVarChar,
500)
{
Value = checkUrl is null
? DBNull.Value
: checkUrl
});
}
command.Parameters.Add(
new SqlParameter(
@@ -1751,7 +1830,13 @@ public sealed class SonicSetupRepository
string? checkUrl =
TlsEndpointProbeService.NormalizeCheckUrl(certificateCheckUrl);
const string sql = """
bool hasCertificateCheckUrl =
await DatabaseSchemaPatcher.HasCertificateCheckUrlColumnAsync(
_connectionString,
cancellationToken);
string sql = hasCertificateCheckUrl
? """
UPDATE [dbo].[SonicContainer]
SET
[CompanyId] = @CompanyId,
@@ -1764,6 +1849,19 @@ public sealed class SonicSetupRepository
[ModifiedBy] = SUSER_SNAME()
WHERE [SonicContainerId] = @SonicContainerId
AND [IsActive] = 1;
"""
: """
UPDATE [dbo].[SonicContainer]
SET
[CompanyId] = @CompanyId,
[SonicConnectionId] = @SonicConnectionId,
[ContainerName] = @ContainerName,
[ContainerDisplayName] = @ContainerDisplayName,
[RestartTimeoutSeconds] = @RestartTimeoutSeconds,
[ModifiedDateTime] = SYSUTCDATETIME(),
[ModifiedBy] = SUSER_SNAME()
WHERE [SonicContainerId] = @SonicContainerId
AND [IsActive] = 1;
""";
await using SqlConnection connection =
@@ -1812,16 +1910,19 @@ public sealed class SonicSetupRepository
: display
});
command.Parameters.Add(
new SqlParameter(
"@CertificateCheckUrl",
SqlDbType.NVarChar,
500)
{
Value = checkUrl is null
? DBNull.Value
: checkUrl
});
if (hasCertificateCheckUrl)
{
command.Parameters.Add(
new SqlParameter(
"@CertificateCheckUrl",
SqlDbType.NVarChar,
500)
{
Value = checkUrl is null
? DBNull.Value
: checkUrl
});
}
command.Parameters.Add(
new SqlParameter(