#8859: Fixing setup errors with PostgreSQL and MySQL (#8861)
Some checks failed
Compile / Compile .NET solution (push) Has been cancelled
Compile / Compile Client-side Assets (push) Has been cancelled
SpecFlow Tests / SpecFlow Tests (push) Has been cancelled

This commit is contained in:
Benedek Farkas
2025-10-29 22:52:34 +01:00
committed by GitHub
parent f0ad335e77
commit 4cfbafd22a
7 changed files with 68 additions and 43 deletions

View File

@@ -73,6 +73,7 @@
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.4.1.0\lib\net472\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin, Version=4.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.4.2.3\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
@@ -82,8 +83,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=6.7.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.7.9\lib\net45\MySql.Data.dll</HintPath>
<Reference Include="MySql.Data, Version=6.10.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.10.9\lib\net452\MySql.Data.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
@@ -101,6 +102,8 @@
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Data" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -110,6 +113,9 @@
<HintPath>..\..\lib\sqlce\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Drawing.Design" />
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
</Reference>
@@ -124,6 +130,7 @@
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.3\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>

View File

@@ -208,12 +208,6 @@
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008,40000,40008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</compilers>
</system.codedom>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient"/>
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.7.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
</DbProviderFactories>
</system.data>
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
<logging level="Error" logLocation="App_data/Logs/Glimpse.log"/>
<tabs>

View File

@@ -12,7 +12,7 @@
<package id="Microsoft.Owin" version="4.2.3" targetFramework="net48" />
<package id="Microsoft.Owin.Host.SystemWeb" version="4.2.3" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="MySql.Data" version="6.7.9" targetFramework="net48" />
<package id="MySql.Data" version="6.10.9" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="Npgsql" version="4.0.17" targetFramework="net48" />
<package id="Orchard.NuGet.Core" version="1.1.0.0" targetFramework="net48" />

View File

@@ -5,9 +5,9 @@ using Orchard.Data.Migration.Schema;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.Features;
using Orchard.Exceptions;
using Orchard.Logging;
using Orchard.Tasks.Locking.Services;
using Orchard.Exceptions;
namespace Orchard.Data.Migration {
/// <summary>
@@ -44,16 +44,21 @@ namespace Orchard.Data.Migration {
public void Activated() {
EnsureDistributedLockSchemaExists();
IDistributedLock @lock;
if (_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(250), out @lock)) {
if (_distributedLockService.TryAcquireLock(
GetType().FullName,
TimeSpan.FromMinutes(30),
TimeSpan.FromMilliseconds(250),
out IDistributedLock @lock)) {
using (@lock) {
// Let's make sure that the basic set of features is enabled. If there are any that are not enabled, then let's enable them first.
// Let's make sure that the basic set of features is enabled.
// If there are any that are not enabled, then let's enable them first.
var theseFeaturesShouldAlwaysBeActive = new[] {
"Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation", "Scheduling", "Settings", "Shapes", "Title"
};
var enabledFeatures = _featureManager.GetEnabledFeatures().Select(f => f.Id).ToList();
var featuresToEnable = theseFeaturesShouldAlwaysBeActive.Where(shouldBeActive => !enabledFeatures.Contains(shouldBeActive)).ToList();
var featuresToEnable = theseFeaturesShouldAlwaysBeActive.Where(
shouldBeActive => !enabledFeatures.Contains(shouldBeActive)).ToList();
if (featuresToEnable.Any()) {
_featureManager.EnableFeatures(featuresToEnable, true);
}
@@ -78,10 +83,10 @@ namespace Orchard.Data.Migration {
}
/// <summary>
/// This ensures that the framework migrations have run for the distributed locking feature, as existing Orchard installations will not have the required tables when upgrading.
/// This ensures that the framework migrations have run for the distributed locking feature, as existing
/// Orchard installations will not have the required tables when upgrading.
/// </summary>
private void EnsureDistributedLockSchemaExists()
{
private void EnsureDistributedLockSchemaExists() {
// Ensure the distributed lock record schema exists.
var schemaBuilder = new SchemaBuilder(_dataMigrationInterpreter);
var distributedLockSchemaBuilder = new DistributedLockSchemaBuilder(_shellSettings, schemaBuilder);
@@ -90,8 +95,6 @@ namespace Orchard.Data.Migration {
// Workaround to avoid some Transaction issue for PostgreSQL.
if (_shellSettings.DataProvider.Equals("PostgreSql", StringComparison.OrdinalIgnoreCase)) {
_transactionManager.RequireNew();
distributedLockSchemaBuilder.CreateSchema();
return;
}
distributedLockSchemaBuilder.CreateSchema();

View File

@@ -97,12 +97,12 @@ namespace Orchard.Data.Migration.Interpreters {
if (columnList.Count > 1) {
sqlCommand.CommandText = $@"
SELECT SUM(CHARACTER_MAXIMUM_LENGTH)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{tableName}'
AND COLUMN_NAME in ({columnNames})
AND TABLE_SCHEMA = '{session.Connection.Database}'
AND (Data_type = 'varchar');";
SELECT SUM(CHARACTER_MAXIMUM_LENGTH)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{tableName}'
AND COLUMN_NAME in ({columnNames})
AND TABLE_SCHEMA = '{session.Connection.Database}'
AND (Data_type = 'varchar');";
using (var reader = sqlCommand.ExecuteReader()) {
reader.Read();
@@ -117,12 +117,12 @@ namespace Orchard.Data.Migration.Interpreters {
}
// Check whether the index contains big nvarchar columns or text fields.
sqlCommand.CommandText = $@"
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{tableName}'
AND COLUMN_NAME in ({columnNames})
AND TABLE_SCHEMA = '{session.Connection.Database}'
AND ((Data_type = 'varchar' and CHARACTER_MAXIMUM_LENGTH > {indexMaximumLength}) OR data_type= 'text');";
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{tableName}'
AND COLUMN_NAME in ({columnNames})
AND TABLE_SCHEMA = '{session.Connection.Database}'
AND ((Data_type = 'varchar' and CHARACTER_MAXIMUM_LENGTH > {indexMaximumLength}) OR data_type= 'text');";
using (var reader = sqlCommand.ExecuteReader()) {
// Provide prefix for string columns with length more than 767.

View File

@@ -9,9 +9,9 @@ using Orchard.Environment.Configuration;
namespace Orchard.Data {
public class NoLockInterceptor : EmptyInterceptor, ISessionInterceptor {
private readonly ShellSettings _shellSettings;
private readonly IEnumerable<INoLockTableProvider> _noLockTableProviders;
private readonly bool _supportsNoLock;
public NoLockInterceptor(
ShellSettings shellSettings,
@@ -19,6 +19,10 @@ namespace Orchard.Data {
_shellSettings = shellSettings;
_noLockTableProviders = noLockTableProviders;
// Only SQL Server supports NOLOCK.
var provider = _shellSettings?.DataProvider?.ToLower();
_supportsNoLock = provider == "sqlserver" || provider == "sqlce";
}
private List<string> _tableNames;
@@ -27,7 +31,7 @@ namespace Orchard.Data {
if (_tableNames == null) {
_tableNames = new List<string>(
_noLockTableProviders
.SelectMany(nltp => nltp.GetTableNames())
.SelectMany(providers => providers.GetTableNames())
.Distinct(StringComparer.OrdinalIgnoreCase)
.Select(n => GetPrefixedTableName(n.Trim())));
}
@@ -45,6 +49,11 @@ namespace Orchard.Data {
// based on https://stackoverflow.com/a/39518098/2669614
public override SqlString OnPrepareStatement(SqlString sql) {
// Skip entirely for providers that do not support NOLOCK
if (!_supportsNoLock) {
return sql;
}
// only work on select queries
if (sql.StartsWithCaseInsensitive("select")) {
// see whether we have anything to add the NOLOCK hint to
@@ -66,7 +75,7 @@ namespace Orchard.Data {
// The captured strings in this group are ordered with respect to where they are
// found in the original string: that means that each string may be contained
// in any, all or none of the following ones in the array. When a captured string
// is part of another, it is so in its entirety, meaning there cannote be a case
// is part of another, it is so in its entirety, meaning there cannot be a case
// when two captured strings intersect partially.
// Take for example the following query:
//
@@ -148,10 +157,11 @@ namespace Orchard.Data {
// starting from the end.
var oFromEnd = outer.OriginalEnd - inner.OriginalIndex;
insertionIndex = outer.Value.Length - oFromEnd;
} else {
}
else {
// outer is still the same as what we captured originally
// we are changing it here for the first time.
// This means the index of our ssubstring within it has not changed
// This means the index of our substring within it has not changed
}
outer.Value = outer.Value
// Remove old substring
@@ -231,7 +241,7 @@ namespace Orchard.Data {
if (tableItem != null) {
// the table is involved in this statement
var tableIndex = parts.IndexOf(tableItem);
// recompute whereIndex in case we added stuff to parts
// re-compute whereIndex in case we added stuff to parts
whereIndex = whereItem != null ? parts.IndexOf(whereItem) : parts.Count;
if (tableIndex > fromIndex && tableIndex < whereIndex) { // sanity check
// if before the table name we have "," or "FROM", this is not a join, but rather
@@ -243,11 +253,13 @@ namespace Orchard.Data {
if (parts[tableIndex + 1].Equals("where", StringComparison.OrdinalIgnoreCase)) {
// There is no alias in the query, so we add "WITH(NOLOCK)" immediately after table name but before the "where" clause.
parts.Insert(tableIndex + 1, "WITH(NOLOCK)");
} else {
}
else {
// We add "WITH(NOLOCK)" after the table alias.
parts.Insert(tableIndex + 2, "WITH(NOLOCK)");
}
} else {
}
else {
// probably doing a join, so edit the next "on" and make it
// "WITH (NOLOCK) on"
for (int i = tableIndex + 1; i < whereIndex; i++) {
@@ -271,6 +283,5 @@ namespace Orchard.Data {
return query;
}
}
}
}

View File

@@ -16,20 +16,30 @@ namespace Orchard.Tasks.Locking.Services {
public void CreateSchema() {
_schemaBuilder.CreateTable(TableName, table => table
.Column<int>("Id", column => column.PrimaryKey().Identity())
.Column<string>("Name", column => column.NotNull().WithLength(512).Unique())
// Keep 512 chars but avoid inline .Unique() to prevent MySQL TEXT/BLOB key-length errors.
.Column<string>("Name", column => column.NotNull().WithLength(512))
.Column<string>("MachineName", column => column.WithLength(256))
.Column<DateTime>("CreatedUtc")
.Column<DateTime>("ValidUntilUtc", column => column.Nullable()));
// MySQL-specific adjustment to avoid error when adding the unique constraint.
if (string.Equals(_shellSettings.DataProvider, "MySql", StringComparison.OrdinalIgnoreCase)) {
// Force VARCHAR(512) on MySQL (some interpreters map >255 to TEXT).
_schemaBuilder.ExecuteSql(
$"ALTER TABLE {_schemaBuilder.TableDbName(TableName)} MODIFY COLUMN Name VARCHAR(512) NOT NULL;",
cmd => cmd.ForProvider("MySql"));
}
_schemaBuilder.AlterTable(TableName, table => {
table.AddUniqueConstraint("UQ_DistributedLockRecord_Name", "Name");
table.CreateIndex("IDX_DistributedLockRecord_Name", "Name");
});
}
public bool SchemaExists() {
try {
var tablePrefix = String.IsNullOrEmpty(_shellSettings.DataTablePrefix) ? "" : _shellSettings.DataTablePrefix + "_";
_schemaBuilder.ExecuteSql(String.Format("select * from {0}{1}", tablePrefix, TableName));
_schemaBuilder.ExecuteSql($"select 1 from {_schemaBuilder.TableDbName(TableName)}");
return true;
}
catch {