mirror of https://github.com/Squidex/squidex.git
Browse Source
* Temp * Simplify tests. * Fix compose. * Only run full test on PRs. * Temp * Temp * Fix writing.pull/1200/head
committed by
GitHub
123 changed files with 8362 additions and 685 deletions
@ -0,0 +1,27 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.EntityFrameworkCore; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Queries; |
|||
|
|||
namespace Squidex; |
|||
|
|||
public abstract class ContentDbContext(string prefix, IJsonSerializer jsonSerializer) : DbContext, IDbContextWithDialect |
|||
{ |
|||
public string Prefix { get; } = prefix; |
|||
|
|||
public abstract SqlDialect Dialect { get; } |
|||
|
|||
protected override void OnModelCreating(ModelBuilder modelBuilder) |
|||
{ |
|||
modelBuilder.UseContent(jsonSerializer, Dialect.JsonColumnType(), Prefix); |
|||
|
|||
base.OnModelCreating(modelBuilder); |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.EntityFrameworkCore; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Queries; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Assets; |
|||
|
|||
internal static class Extensions |
|||
{ |
|||
public static AssetSqlQueryBuilder AssetQuery<T>(this DbContext dbContext, SqlParams? parameters = null) |
|||
{ |
|||
if (dbContext is not IDbContextWithDialect withDialect) |
|||
{ |
|||
throw new InvalidOperationException("Invalid context."); |
|||
} |
|||
|
|||
var tableName = dbContext.Model.FindEntityType(typeof(T))?.GetTableName() |
|||
?? throw new InvalidOperationException("Unknown model."); |
|||
|
|||
return new AssetSqlQueryBuilder(withDialect.Dialect, tableName, parameters); |
|||
} |
|||
} |
|||
@ -0,0 +1,158 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Squidex.Infrastructure; |
|||
|
|||
#pragma warning disable MA0048 // File name must match type name
|
|||
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
|
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents; |
|||
|
|||
public readonly record struct DynamicContextName(DomainId AppId, DomainId SchemaId); |
|||
|
|||
public sealed class DynamicTables<TContext, TContentContext>( |
|||
IDbContextFactory<TContext> dbContextFactory, |
|||
IDbContextNamedFactory<TContentContext> dbContextNamedFactory) |
|||
where TContext : DbContext where TContentContext : ContentDbContext |
|||
{ |
|||
private readonly Dictionary<DynamicContextName, Task<string>> cachedMappings = []; |
|||
|
|||
public async IAsyncEnumerable<DynamicContextName> GetContextNames( |
|||
[EnumeratorCancellation] CancellationToken ct) |
|||
{ |
|||
using var dbContext = await dbContextFactory.CreateDbContextAsync(ct); |
|||
|
|||
var tableEntities = await dbContext.Set<EFContentTableEntity>().ToListAsync(ct); |
|||
|
|||
lock (cachedMappings) |
|||
{ |
|||
foreach (var entity in tableEntities) |
|||
{ |
|||
var name = new DynamicContextName(entity.AppId, entity.SchemaId); |
|||
if (!cachedMappings.ContainsKey(name)) |
|||
{ |
|||
cachedMappings[name] = Task.FromResult(Prefix(entity)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
foreach (var entity in tableEntities) |
|||
{ |
|||
yield return new DynamicContextName(entity.AppId, entity.SchemaId); |
|||
} |
|||
} |
|||
|
|||
public async Task<TContentContext> CreateDbContextAsync(DomainId appId, DomainId schemaId, |
|||
CancellationToken ct) |
|||
{ |
|||
var prefix = await EnsureDbContextAsync(appId, schemaId); |
|||
|
|||
return await dbContextNamedFactory.CreateDbContextAsync(prefix, ct); |
|||
} |
|||
|
|||
public async Task<TContentContext> CreateDbContextAsync(DynamicContextName name, |
|||
CancellationToken ct) |
|||
{ |
|||
var prefix = await EnsureDbContextAsync(name); |
|||
|
|||
return await dbContextNamedFactory.CreateDbContextAsync(prefix, ct); |
|||
} |
|||
|
|||
public async Task<string> EnsureDbContextAsync(DomainId appId, DomainId schemaId) |
|||
{ |
|||
return await EnsureDbContextAsync(new DynamicContextName(appId, schemaId)); |
|||
} |
|||
|
|||
public async Task<string> EnsureDbContextAsync(DynamicContextName name) |
|||
{ |
|||
Guard.NotDefault(name); |
|||
|
|||
async Task<string> PrepareAsync() |
|||
{ |
|||
var prefix = await GetPrefixAsync(name); |
|||
|
|||
using var dbContext = await dbContextNamedFactory.CreateDbContextAsync(prefix, default); |
|||
|
|||
// Make the prefix available as async local variable because migrations cannot use it otherwise.
|
|||
TableName.Prefix = prefix; |
|||
await dbContext.Database.MigrateAsync(default); |
|||
|
|||
return prefix; |
|||
} |
|||
|
|||
Task<string> preparation; |
|||
lock (cachedMappings) |
|||
{ |
|||
if (!cachedMappings.TryGetValue(name, out var temp)) |
|||
{ |
|||
temp = PrepareAsync(); |
|||
cachedMappings[name] = temp; |
|||
} |
|||
|
|||
preparation = temp; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
return await preparation; |
|||
} |
|||
catch |
|||
{ |
|||
// Do not cache errors forever, otherwise we would not be able to recover.
|
|||
lock (cachedMappings) |
|||
{ |
|||
if (cachedMappings.TryGetValue(name, out var temp) && ReferenceEquals(temp, preparation)) |
|||
{ |
|||
cachedMappings.Remove(name); |
|||
} |
|||
} |
|||
|
|||
throw; |
|||
} |
|||
} |
|||
|
|||
private async Task<string> GetPrefixAsync(DynamicContextName name) |
|||
{ |
|||
var prefix = string.Empty; |
|||
|
|||
await using var dbContext = await dbContextFactory.CreateDbContextAsync(default); |
|||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
|||
try |
|||
{ |
|||
var entity = new EFContentTableEntity { AppId = name.AppId, SchemaId = name.SchemaId }; |
|||
|
|||
await dbContext.Set<EFContentTableEntity>().AddAsync(entity, default); |
|||
await dbContext.SaveChangesAsync(default); |
|||
|
|||
prefix = Prefix(entity); |
|||
} |
|||
catch |
|||
{ |
|||
// Very likely a unique index exception.
|
|||
} |
|||
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
|||
|
|||
if (string.IsNullOrWhiteSpace(prefix)) |
|||
{ |
|||
var existing = |
|||
await dbContext.Set<EFContentTableEntity>().Where(x => x.AppId == name.AppId && x.SchemaId == name.SchemaId) |
|||
.FirstOrDefaultAsync(default) |
|||
?? throw new InvalidOperationException("Cannot resolve mapping table for schema."); |
|||
|
|||
prefix = Prefix(existing); |
|||
} |
|||
|
|||
return prefix; |
|||
} |
|||
|
|||
private static string Prefix(EFContentTableEntity entity) |
|||
{ |
|||
return $"__c{entity.Id}_"; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents; |
|||
|
|||
public sealed class EFContentTableEntity |
|||
{ |
|||
public long Id { get; set; } |
|||
|
|||
public DomainId AppId { get; set; } |
|||
|
|||
public DomainId SchemaId { get; set; } |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.EntityFrameworkCore; |
|||
using Squidex.Infrastructure.Json; |
|||
|
|||
namespace Squidex.Infrastructure; |
|||
|
|||
public sealed class DelegatingDbNamedContextFactory<TContext>( |
|||
IJsonSerializer jsonSerializer, |
|||
Func<IJsonSerializer, string, TContext> factory) |
|||
: IDbContextNamedFactory<TContext> where TContext : DbContext |
|||
{ |
|||
public Task<TContext> CreateDbContextAsync(string name, |
|||
CancellationToken ct = default) |
|||
{ |
|||
return Task.FromResult(factory(jsonSerializer, name)); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace Squidex.Infrastructure; |
|||
|
|||
public interface IDbContextNamedFactory<TContext> where TContext : DbContext |
|||
{ |
|||
Task<TContext> CreateDbContextAsync(string name, |
|||
CancellationToken ct = default); |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure.Queries; |
|||
|
|||
namespace Squidex.Infrastructure; |
|||
|
|||
public interface IDbContextWithDialect |
|||
{ |
|||
SqlDialect Dialect { get; } |
|||
} |
|||
@ -1,5 +1,4 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Metadata; |
|||
using Microsoft.EntityFrameworkCore.Metadata; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
File diff suppressed because it is too large
@ -0,0 +1,71 @@ |
|||
using Microsoft.EntityFrameworkCore.Metadata; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.MySql.App.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class AddContentTable : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesPublished", |
|||
type: "varchar(255)", |
|||
maxLength: 255, |
|||
nullable: false, |
|||
defaultValue: "00000000-0000-0000-0000-000000000000") |
|||
.Annotation("MySql:CharSet", "utf8mb4"); |
|||
|
|||
migrationBuilder.AddColumn<string>( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesAll", |
|||
type: "varchar(255)", |
|||
maxLength: 255, |
|||
nullable: false, |
|||
defaultValue: "00000000-0000-0000-0000-000000000000") |
|||
.Annotation("MySql:CharSet", "utf8mb4"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "ContentTables", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<long>(type: "bigint", nullable: false) |
|||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
|||
AppId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
SchemaId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4") |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_ContentTables", x => x.Id); |
|||
}) |
|||
.Annotation("MySql:CharSet", "utf8mb4"); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_ContentTables_AppId_SchemaId", |
|||
table: "ContentTables", |
|||
columns: new[] { "AppId", "SchemaId" }, |
|||
unique: true); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "ContentTables"); |
|||
|
|||
migrationBuilder.DropColumn( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesPublished"); |
|||
|
|||
migrationBuilder.DropColumn( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesAll"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
// <auto-generated />
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Metadata; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
|||
using Squidex.Providers.MySql.Content; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.MySql.Content.Migrations |
|||
{ |
|||
[DbContext(typeof(MySqlContentDbContext))] |
|||
[Migration("20250305193148_AddInitial")] |
|||
partial class AddInitial |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void BuildTargetModel(ModelBuilder modelBuilder) |
|||
{ |
|||
#pragma warning disable 612, 618
|
|||
modelBuilder |
|||
.HasAnnotation("ProductVersion", "8.0.13") |
|||
.HasAnnotation("Relational:MaxIdentifierLength", 64); |
|||
|
|||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentCompleteEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("tinyint(1)"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsAll", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentPublishedEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("tinyint(1)"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsPublished", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.MySql.Content.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class AddInitial : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AlterDatabase() |
|||
.Annotation("MySql:CharSet", "utf8mb4"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: $"{TableName.Prefix}ContentsAll", |
|||
columns: table => new |
|||
{ |
|||
DocumentId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Id = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
CreatedBy = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
LastModifiedBy = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Created = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false), |
|||
LastModified = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false), |
|||
Version = table.Column<long>(type: "bigint", nullable: false), |
|||
AppId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
IsDeleted = table.Column<bool>(type: "tinyint(1)", nullable: false), |
|||
SchemaId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
NewStatus = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Status = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Data = table.Column<string>(type: "json", nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
ScheduleJob = table.Column<string>(type: "json", nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
IndexedAppId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
IndexedSchemaId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
ScheduledAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true), |
|||
NewData = table.Column<string>(type: "json", nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
TranslationStatus = table.Column<string>(type: "json", nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4") |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey($"PK_{TableName.Prefix}ContentsAll", x => x.DocumentId); |
|||
}) |
|||
.Annotation("MySql:CharSet", "utf8mb4"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: $"{TableName.Prefix}ContentsPublished", |
|||
columns: table => new |
|||
{ |
|||
DocumentId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Id = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
CreatedBy = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
LastModifiedBy = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Created = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false), |
|||
LastModified = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false), |
|||
Version = table.Column<long>(type: "bigint", nullable: false), |
|||
AppId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
IsDeleted = table.Column<bool>(type: "tinyint(1)", nullable: false), |
|||
SchemaId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
NewStatus = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Status = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Data = table.Column<string>(type: "json", nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
ScheduleJob = table.Column<string>(type: "json", nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
IndexedAppId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
IndexedSchemaId = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
ScheduledAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true), |
|||
NewData = table.Column<string>(type: "json", nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
TranslationStatus = table.Column<string>(type: "json", nullable: true) |
|||
.Annotation("MySql:CharSet", "utf8mb4") |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey($"PK_{TableName.Prefix}ContentsPublished", x => x.DocumentId); |
|||
}) |
|||
.Annotation("MySql:CharSet", "utf8mb4"); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: $"{TableName.Prefix}ContentsAll"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: $"{TableName.Prefix}ContentsPublished"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
// <auto-generated />
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Metadata; |
|||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
|||
using Squidex.Providers.MySql.Content; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.MySql.Content.Migrations |
|||
{ |
|||
[DbContext(typeof(MySqlContentDbContext))] |
|||
partial class MySqlContentDbContextModelSnapshot : ModelSnapshot |
|||
{ |
|||
protected override void BuildModel(ModelBuilder modelBuilder) |
|||
{ |
|||
#pragma warning disable 612, 618
|
|||
modelBuilder |
|||
.HasAnnotation("ProductVersion", "8.0.13") |
|||
.HasAnnotation("Relational:MaxIdentifierLength", 64); |
|||
|
|||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentCompleteEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("tinyint(1)"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsAll", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentPublishedEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("tinyint(1)"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetime(6)"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("varchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("varchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("json"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsPublished", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.EntityFrameworkCore; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Queries; |
|||
|
|||
#pragma warning disable CS9107 // Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well.
|
|||
|
|||
namespace Squidex.Providers.MySql.Content; |
|||
|
|||
public sealed class MySqlContentDbContext(string prefix, string connectionString, string? versionString, IJsonSerializer jsonSerializer) |
|||
: ContentDbContext(prefix, jsonSerializer) |
|||
{ |
|||
public override SqlDialect Dialect => MySqlDialect.Instance; |
|||
|
|||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) |
|||
{ |
|||
var version = |
|||
!string.IsNullOrWhiteSpace(versionString) ? |
|||
ServerVersion.Parse(versionString) : |
|||
ServerVersion.AutoDetect(connectionString); |
|||
|
|||
optionsBuilder.SetDefaultWarnings(); |
|||
optionsBuilder.UseMySql(connectionString, version, options => |
|||
{ |
|||
options.UseMicrosoftJson(MySqlCommonJsonChangeTrackingOptions.FullHierarchyOptimizedSemantically); |
|||
options.MigrationsHistoryTable($"{prefix}MigrationHistory"); |
|||
}); |
|||
|
|||
base.OnConfiguring(optionsBuilder); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using Microsoft.EntityFrameworkCore.Design; |
|||
using Squidex.Infrastructure.Json.System; |
|||
|
|||
namespace Squidex.Providers.MySql.Content; |
|||
|
|||
public sealed class MySqlContentDbContextDesignTimeFactory : IDesignTimeDbContextFactory<MySqlContentDbContext> |
|||
{ |
|||
public MySqlContentDbContext CreateDbContext(string[] args) |
|||
{ |
|||
const string ConnectionString = "Server=localhost;Port=33060;Database=test;User=mysql;Password=mysql"; |
|||
|
|||
return new MySqlContentDbContext(string.Empty, ConnectionString, null, new SystemJsonSerializer(JsonSerializerOptions.Default)); |
|||
} |
|||
} |
|||
@ -1,5 +1,4 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; |
|||
|
|||
#nullable disable |
|||
File diff suppressed because it is too large
@ -0,0 +1,66 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.Postgres.App.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class AddContentTable : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesPublished", |
|||
type: "character varying(255)", |
|||
maxLength: 255, |
|||
nullable: false, |
|||
defaultValue: "00000000-0000-0000-0000-000000000000"); |
|||
|
|||
migrationBuilder.AddColumn<string>( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesAll", |
|||
type: "character varying(255)", |
|||
maxLength: 255, |
|||
nullable: false, |
|||
defaultValue: "00000000-0000-0000-0000-000000000000"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "ContentTables", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<long>(type: "bigint", nullable: false) |
|||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), |
|||
AppId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
SchemaId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_ContentTables", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_ContentTables_AppId_SchemaId", |
|||
table: "ContentTables", |
|||
columns: new[] { "AppId", "SchemaId" }, |
|||
unique: true); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "ContentTables"); |
|||
|
|||
migrationBuilder.DropColumn( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesPublished"); |
|||
|
|||
migrationBuilder.DropColumn( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesAll"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
// <auto-generated />
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
|||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; |
|||
using Squidex.Providers.Postgres.Content; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.Postgres.Content.Migrations |
|||
{ |
|||
[DbContext(typeof(PostgresContentDbContext))] |
|||
[Migration("20250305193154_AddInitial")] |
|||
partial class AddInitial |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void BuildTargetModel(ModelBuilder modelBuilder) |
|||
{ |
|||
#pragma warning disable 612, 618
|
|||
modelBuilder |
|||
.HasAnnotation("ProductVersion", "8.0.13") |
|||
.HasAnnotation("Relational:MaxIdentifierLength", 63); |
|||
|
|||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentCompleteEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("boolean"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsAll", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentPublishedEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("boolean"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsPublished", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.Postgres.Content.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class AddInitial : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.CreateTable( |
|||
name: $"{TableName.Prefix}ContentsAll", |
|||
columns: table => new |
|||
{ |
|||
DocumentId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
Id = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
CreatedBy = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false), |
|||
LastModifiedBy = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false), |
|||
Created = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false), |
|||
LastModified = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false), |
|||
Version = table.Column<long>(type: "bigint", nullable: false), |
|||
AppId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
IsDeleted = table.Column<bool>(type: "boolean", nullable: false), |
|||
SchemaId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
NewStatus = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true), |
|||
Status = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false), |
|||
Data = table.Column<string>(type: "jsonb", nullable: false), |
|||
ScheduleJob = table.Column<string>(type: "jsonb", nullable: true), |
|||
IndexedAppId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
IndexedSchemaId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
ScheduledAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true), |
|||
NewData = table.Column<string>(type: "jsonb", nullable: true), |
|||
TranslationStatus = table.Column<string>(type: "jsonb", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey($"PK_{TableName.Prefix}ContentsAll", x => x.DocumentId); |
|||
}); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: $"{TableName.Prefix}ContentsPublished", |
|||
columns: table => new |
|||
{ |
|||
DocumentId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
Id = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
CreatedBy = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false), |
|||
LastModifiedBy = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false), |
|||
Created = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false), |
|||
LastModified = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false), |
|||
Version = table.Column<long>(type: "bigint", nullable: false), |
|||
AppId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
IsDeleted = table.Column<bool>(type: "boolean", nullable: false), |
|||
SchemaId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
NewStatus = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true), |
|||
Status = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false), |
|||
Data = table.Column<string>(type: "jsonb", nullable: false), |
|||
ScheduleJob = table.Column<string>(type: "jsonb", nullable: true), |
|||
IndexedAppId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
IndexedSchemaId = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false), |
|||
ScheduledAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true), |
|||
NewData = table.Column<string>(type: "jsonb", nullable: true), |
|||
TranslationStatus = table.Column<string>(type: "jsonb", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey($"PK_{TableName.Prefix}ContentsPublished", x => x.DocumentId); |
|||
}); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: $"{TableName.Prefix}ContentsAll"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: $"{TableName.Prefix}ContentsPublished"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
// <auto-generated />
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
|||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; |
|||
using Squidex.Providers.Postgres.Content; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.Postgres.Content.Migrations |
|||
{ |
|||
[DbContext(typeof(PostgresContentDbContext))] |
|||
partial class PostgresContentDbContextModelSnapshot : ModelSnapshot |
|||
{ |
|||
protected override void BuildModel(ModelBuilder modelBuilder) |
|||
{ |
|||
#pragma warning disable 612, 618
|
|||
modelBuilder |
|||
.HasAnnotation("ProductVersion", "8.0.13") |
|||
.HasAnnotation("Relational:MaxIdentifierLength", 63); |
|||
|
|||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentCompleteEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("boolean"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsAll", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentPublishedEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("boolean"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("timestamp with time zone"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("character varying(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("character varying(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("jsonb"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsPublished", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.EntityFrameworkCore; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Queries; |
|||
|
|||
#pragma warning disable CS9107 // Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well.
|
|||
|
|||
namespace Squidex.Providers.Postgres.Content; |
|||
|
|||
public sealed class PostgresContentDbContext(string prefix, string connectionString, IJsonSerializer jsonSerializer) |
|||
: ContentDbContext(prefix, jsonSerializer) |
|||
{ |
|||
public override SqlDialect Dialect => PostgresDialect.Instance; |
|||
|
|||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) |
|||
{ |
|||
optionsBuilder.SetDefaultWarnings(); |
|||
optionsBuilder.UseNpgsql(connectionString, options => |
|||
{ |
|||
options.MigrationsHistoryTable($"{prefix}MigrationHistory"); |
|||
}); |
|||
|
|||
base.OnConfiguring(optionsBuilder); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using Microsoft.EntityFrameworkCore.Design; |
|||
using Squidex.Infrastructure.Json.System; |
|||
|
|||
namespace Squidex.Providers.Postgres.Content; |
|||
|
|||
public sealed class PostgresContentDbContextDesignTimeFactory : IDesignTimeDbContextFactory<PostgresContentDbContext> |
|||
{ |
|||
public PostgresContentDbContext CreateDbContext(string[] args) |
|||
{ |
|||
const string ConnectionString = "Server=localhost;Port=54320;Database=test;User=postgres;Password=postgres"; |
|||
|
|||
return new PostgresContentDbContext(string.Empty, ConnectionString, new SystemJsonSerializer(JsonSerializerOptions.Default)); |
|||
} |
|||
} |
|||
@ -1,5 +1,4 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
File diff suppressed because it is too large
@ -0,0 +1,65 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.SqlServer.App.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class AddContentTable : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesPublished", |
|||
type: "nvarchar(255)", |
|||
maxLength: 255, |
|||
nullable: false, |
|||
defaultValue: "00000000-0000-0000-0000-000000000000"); |
|||
|
|||
migrationBuilder.AddColumn<string>( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesAll", |
|||
type: "nvarchar(255)", |
|||
maxLength: 255, |
|||
nullable: false, |
|||
defaultValue: "00000000-0000-0000-0000-000000000000"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "ContentTables", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<long>(type: "bigint", nullable: false) |
|||
.Annotation("SqlServer:Identity", "1, 1"), |
|||
AppId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
SchemaId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_ContentTables", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_ContentTables_AppId_SchemaId", |
|||
table: "ContentTables", |
|||
columns: new[] { "AppId", "SchemaId" }, |
|||
unique: true); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "ContentTables"); |
|||
|
|||
migrationBuilder.DropColumn( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesPublished"); |
|||
|
|||
migrationBuilder.DropColumn( |
|||
name: "FromSchema", |
|||
table: "ContentReferencesAll"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
// <auto-generated />
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Metadata; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
|||
using Squidex.Providers.SqlServer.Content; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.SqlServer.Content.Migrations |
|||
{ |
|||
[DbContext(typeof(SqlServerContentDbContext))] |
|||
[Migration("20250305193200_AddInitial")] |
|||
partial class AddInitial |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void BuildTargetModel(ModelBuilder modelBuilder) |
|||
{ |
|||
#pragma warning disable 612, 618
|
|||
modelBuilder |
|||
.HasAnnotation("ProductVersion", "8.0.13") |
|||
.HasAnnotation("Relational:MaxIdentifierLength", 128); |
|||
|
|||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentCompleteEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("bit"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsAll", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentPublishedEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("bit"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsPublished", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.SqlServer.Content.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class AddInitial : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.CreateTable( |
|||
name: $"{TableName.Prefix}ContentsAll", |
|||
columns: table => new |
|||
{ |
|||
DocumentId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
Id = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
CreatedBy = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), |
|||
LastModifiedBy = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), |
|||
Created = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false), |
|||
LastModified = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false), |
|||
Version = table.Column<long>(type: "bigint", nullable: false), |
|||
AppId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false), |
|||
SchemaId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
NewStatus = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true), |
|||
Status = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), |
|||
Data = table.Column<string>(type: "nvarchar(max)", nullable: false), |
|||
ScheduleJob = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
IndexedAppId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
IndexedSchemaId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
ScheduledAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true), |
|||
NewData = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
TranslationStatus = table.Column<string>(type: "nvarchar(max)", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey($"PK_{TableName.Prefix}ContentsAll", x => x.DocumentId); |
|||
}); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: $"{TableName.Prefix}ContentsPublished", |
|||
columns: table => new |
|||
{ |
|||
DocumentId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
Id = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
CreatedBy = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), |
|||
LastModifiedBy = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), |
|||
Created = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false), |
|||
LastModified = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false), |
|||
Version = table.Column<long>(type: "bigint", nullable: false), |
|||
AppId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false), |
|||
SchemaId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
NewStatus = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true), |
|||
Status = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), |
|||
Data = table.Column<string>(type: "nvarchar(max)", nullable: false), |
|||
ScheduleJob = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
IndexedAppId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
IndexedSchemaId = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
ScheduledAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true), |
|||
NewData = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
TranslationStatus = table.Column<string>(type: "nvarchar(max)", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey($"PK_{TableName.Prefix}ContentsPublished", x => x.DocumentId); |
|||
}); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: $"{TableName.Prefix}ContentsAll"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: $"{TableName.Prefix}ContentsPublished"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
// <auto-generated />
|
|||
using System; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Metadata; |
|||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
|||
using Squidex.Providers.SqlServer.Content; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Squidex.Providers.SqlServer.Content.Migrations |
|||
{ |
|||
[DbContext(typeof(SqlServerContentDbContext))] |
|||
partial class SqlServerContentDbContextModelSnapshot : ModelSnapshot |
|||
{ |
|||
protected override void BuildModel(ModelBuilder modelBuilder) |
|||
{ |
|||
#pragma warning disable 612, 618
|
|||
modelBuilder |
|||
.HasAnnotation("ProductVersion", "8.0.13") |
|||
.HasAnnotation("Relational:MaxIdentifierLength", 128); |
|||
|
|||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentCompleteEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("bit"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsAll", (string)null); |
|||
}); |
|||
|
|||
modelBuilder.Entity("Squidex.Domain.Apps.Entities.Contents.EFContentPublishedEntity", b => |
|||
{ |
|||
b.Property<string>("DocumentId") |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("AppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<DateTimeOffset>("Created") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("CreatedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("Data") |
|||
.IsRequired() |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("Id") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedAppId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("IndexedSchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<bool>("IsDeleted") |
|||
.HasColumnType("bit"); |
|||
|
|||
b.Property<DateTimeOffset>("LastModified") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("LastModifiedBy") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("NewData") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<string>("NewStatus") |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("ScheduleJob") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<DateTimeOffset?>("ScheduledAt") |
|||
.HasColumnType("datetimeoffset"); |
|||
|
|||
b.Property<string>("SchemaId") |
|||
.IsRequired() |
|||
.HasMaxLength(255) |
|||
.HasColumnType("nvarchar(255)"); |
|||
|
|||
b.Property<string>("Status") |
|||
.IsRequired() |
|||
.HasMaxLength(100) |
|||
.HasColumnType("nvarchar(100)"); |
|||
|
|||
b.Property<string>("TranslationStatus") |
|||
.HasColumnType("nvarchar(max)"); |
|||
|
|||
b.Property<long>("Version") |
|||
.HasColumnType("bigint"); |
|||
|
|||
b.HasKey("DocumentId"); |
|||
|
|||
b.ToTable("ContentsPublished", (string)null); |
|||
}); |
|||
#pragma warning restore 612, 618
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.EntityFrameworkCore; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Queries; |
|||
|
|||
#pragma warning disable CS9107 // Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well.
|
|||
|
|||
namespace Squidex.Providers.SqlServer.Content; |
|||
|
|||
public sealed class SqlServerContentDbContext(string prefix, string connectionString, IJsonSerializer jsonSerializer) |
|||
: ContentDbContext(prefix, jsonSerializer) |
|||
{ |
|||
public override SqlDialect Dialect => SqlServerDialect.Instance; |
|||
|
|||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) |
|||
{ |
|||
optionsBuilder.SetDefaultWarnings(); |
|||
optionsBuilder.UseSqlServer(connectionString, options => |
|||
{ |
|||
options.MigrationsHistoryTable($"{prefix}MigrationHistory"); |
|||
}); |
|||
|
|||
base.OnConfiguring(optionsBuilder); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using Microsoft.EntityFrameworkCore.Design; |
|||
using Squidex.Infrastructure.Json.System; |
|||
|
|||
namespace Squidex.Providers.SqlServer.Content; |
|||
|
|||
public sealed class SqlServerContentDbContextDesignTimeFactory : IDesignTimeDbContextFactory<SqlServerContentDbContext> |
|||
{ |
|||
public SqlServerContentDbContext CreateDbContext(string[] args) |
|||
{ |
|||
const string ConnectionString = "Server=localhost;Port=14330;Database=test;User=sa;Password=sqlserver"; |
|||
|
|||
return new SqlServerContentDbContext(string.Empty, ConnectionString, new SystemJsonSerializer(JsonSerializerOptions.Default)); |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
namespace Squidex; |
|||
|
|||
public static class TableName |
|||
{ |
|||
private static readonly AsyncLocal<string> CurrentPrefix = new AsyncLocal<string>(); |
|||
|
|||
public static string Prefix |
|||
{ |
|||
get => CurrentPrefix.Value ?? string.Empty; |
|||
set => CurrentPrefix.Value = value; |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
# Stop the script when a cmdlet or a native command fails |
|||
$ErrorActionPreference = 'Stop' |
|||
|
|||
$migrationName = $args[0] |
|||
|
|||
dotnet ef migrations add $migrationName --context MysqlContentDbContext -o Providers/MySql/Content/Migrations |
|||
if (!$?) { |
|||
Write-Error "Creating migration failed for MySql" |
|||
exit 1 |
|||
} |
|||
|
|||
dotnet ef migrations add $migrationName --context PostgresContentDbContext -o Providers/Postgres/Content/Migrations |
|||
if (!$?) { |
|||
Write-Error "Creating migration failed for Postgres" |
|||
exit 1 |
|||
} |
|||
|
|||
dotnet ef migrations add $migrationName --context SqlServerContentDbContext -o Providers/SqlServer/Content/Migrations |
|||
if (!$?) { |
|||
Write-Error "Creating migration failed for SqlServer" |
|||
exit 1 |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Concurrent; |
|||
using MongoDB.Driver; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents; |
|||
|
|||
internal class CollectionProvider(IMongoClient mongoClient, string prefixDatabase, string prefixCollection) |
|||
{ |
|||
private readonly ConcurrentDictionary<(DomainId, DomainId), Task<IMongoCollection<MongoContentEntity>>> collections = |
|||
new ConcurrentDictionary<(DomainId, DomainId), Task<IMongoCollection<MongoContentEntity>>>(); |
|||
|
|||
public Task<IMongoCollection<MongoContentEntity>> GetCollectionAsync(DomainId appId, DomainId schemaId) |
|||
{ |
|||
return collections.GetOrAdd((appId, schemaId), CreateCollectionAsync); |
|||
} |
|||
|
|||
private async Task<IMongoCollection<MongoContentEntity>> CreateCollectionAsync((DomainId, DomainId) key) |
|||
{ |
|||
var (appId, schemaId) = key; |
|||
|
|||
var schemaDatabase = mongoClient.GetDatabase($"{prefixDatabase}_{appId}"); |
|||
var schemaCollection = schemaDatabase.GetCollection<MongoContentEntity>($"{prefixCollection}_{schemaId}"); |
|||
|
|||
await schemaCollection.Indexes.CreateManyAsync( |
|||
[ |
|||
new CreateIndexModel<MongoContentEntity>( |
|||
Builders<MongoContentEntity>.IndexKeys |
|||
.Descending(x => x.LastModified) |
|||
.Ascending(x => x.Id) |
|||
.Ascending(x => x.IsDeleted) |
|||
.Ascending(x => x.ReferencedIds)), |
|||
new CreateIndexModel<MongoContentEntity>( |
|||
Builders<MongoContentEntity>.IndexKeys |
|||
.Ascending(x => x.IndexedSchemaId) |
|||
.Ascending(x => x.IsDeleted) |
|||
.Descending(x => x.LastModified)), |
|||
]); |
|||
|
|||
return schemaCollection; |
|||
} |
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text; |
|||
using HandlebarsDotNet; |
|||
using Microsoft.CodeAnalysis; |
|||
using Microsoft.CodeAnalysis.CSharp; |
|||
using Microsoft.CodeAnalysis.CSharp.Syntax; |
|||
using Microsoft.CodeAnalysis.Text; |
|||
|
|||
namespace Squidex.Data.Tests.CodeGenerator; |
|||
|
|||
[Generator] |
|||
public class CodeGenerator : IIncrementalGenerator |
|||
{ |
|||
public void Initialize(IncrementalGeneratorInitializationContext context) |
|||
{ |
|||
static TestModel? TransformTest(GeneratorSyntaxContext ctx) |
|||
{ |
|||
var classSyntax = (ClassDeclarationSyntax)ctx.Node; |
|||
|
|||
var className = classSyntax.Identifier.Text; |
|||
if (!className.StartsWith("EF", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (!classSyntax.Modifiers.Any(x => x.IsKind(SyntaxKind.AbstractKeyword))) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (classSyntax.TypeParameterList == null || |
|||
classSyntax.TypeParameterList.Parameters.Count == 0 || |
|||
classSyntax.TypeParameterList.Parameters[0].Identifier.Text != "TContext") |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var reuseLabel = "default"; |
|||
foreach (var attributeList in classSyntax.AttributeLists) |
|||
{ |
|||
foreach (var attribute in attributeList.Attributes) |
|||
{ |
|||
var name = attribute.Name.ToString(); |
|||
if (name != "ReuseLabel" && name != "ReuseLabelAttribute") |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (attribute.ArgumentList?.Arguments.Count != 1) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var value = attribute.ArgumentList.Arguments[0]; |
|||
if (value.Expression is not LiteralExpressionSyntax literal) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var candidate = literal.Token.ValueText; |
|||
if (!string.IsNullOrWhiteSpace(candidate)) |
|||
{ |
|||
reuseLabel = candidate; |
|||
} |
|||
} |
|||
} |
|||
|
|||
var namespaceDeclaration = |
|||
classSyntax.Ancestors() |
|||
.OfType<BaseNamespaceDeclarationSyntax>().First(); |
|||
|
|||
return new TestModel |
|||
{ |
|||
BaseName = classSyntax.Identifier.Text, |
|||
ClassName = classSyntax.Identifier.Text.Substring(2), |
|||
ClassNamespace = namespaceDeclaration.Name.ToString(), |
|||
CollectionSuffix = reuseLabel.ToPascalCase(), |
|||
CollectionLabel = reuseLabel, |
|||
HasContentContext = classSyntax.TypeParameterList.Parameters.Count == 2, |
|||
}; |
|||
} |
|||
|
|||
var fieldDeclarations = context.SyntaxProvider.CreateSyntaxProvider( |
|||
static (node, _) => |
|||
{ |
|||
return node is ClassDeclarationSyntax; |
|||
}, |
|||
static (ctx, _) => TransformTest(ctx)) |
|||
.Where(x => x != null); |
|||
|
|||
WriteTests(context, fieldDeclarations); |
|||
WriteFixtures(context, fieldDeclarations!); |
|||
} |
|||
|
|||
private static void WriteTests(IncrementalGeneratorInitializationContext context, IncrementalValuesProvider<TestModel?> fieldDeclarations) |
|||
{ |
|||
var testTemplateStream = typeof(CodeGenerator).Assembly.GetManifestResourceStream("Squidex.TestTemplate.handlebar")!; |
|||
var testTemplateText = new StreamReader(testTemplateStream).ReadToEnd(); |
|||
var testTemplateFunc = Handlebars.Compile(testTemplateText); |
|||
|
|||
context.RegisterSourceOutput(fieldDeclarations, (context, model) => |
|||
{ |
|||
var source = testTemplateFunc(model); |
|||
|
|||
context.AddSource($"{model!.BaseName}_Tests.cs", SourceText.From(source, Encoding.UTF8)); |
|||
}); |
|||
} |
|||
|
|||
private static void WriteFixtures(IncrementalGeneratorInitializationContext context, IncrementalValuesProvider<TestModel> fieldDeclarations) |
|||
{ |
|||
var fixtureTemplateStream = typeof(CodeGenerator).Assembly.GetManifestResourceStream("Squidex.FixtureTemplate.handlebar")!; |
|||
var fixtureTemplateText = new StreamReader(fixtureTemplateStream).ReadToEnd(); |
|||
var fixtureTemplateFunc = Handlebars.Compile(fixtureTemplateText); |
|||
|
|||
var fixtureDeclarations = fieldDeclarations.Select( |
|||
static (x, ct) => |
|||
{ |
|||
return new FixtureModel { Label = x.CollectionLabel, Name = x.CollectionSuffix }; |
|||
}) |
|||
.Collect().SelectMany((values, _) => values.GroupBy(x => x.Label).Select(x => x.First())); |
|||
|
|||
context.RegisterSourceOutput(fixtureDeclarations, (context, model) => |
|||
{ |
|||
var source = fixtureTemplateFunc(model); |
|||
|
|||
context.AddSource($"{model.Name}_Fixtures.cs", SourceText.From(source, Encoding.UTF8)); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text; |
|||
|
|||
namespace Squidex; |
|||
|
|||
public static class Extensions |
|||
{ |
|||
private const char NullChar = (char)0; |
|||
|
|||
public static string ToPascalCase(this string value) |
|||
{ |
|||
return value.AsSpan().ToPascalCase(); |
|||
} |
|||
|
|||
public static string ToPascalCase(this ReadOnlySpan<char> value) |
|||
{ |
|||
if (value.Length == 0) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
var sb = new StringBuilder(value.Length); |
|||
|
|||
var last = NullChar; |
|||
var length = 0; |
|||
|
|||
for (var i = 0; i < value.Length; i++) |
|||
{ |
|||
var c = value[i]; |
|||
|
|||
if (c == '-' || c == '_' || c == ' ') |
|||
{ |
|||
if (last != NullChar) |
|||
{ |
|||
sb.Append(char.ToUpperInvariant(last)); |
|||
} |
|||
|
|||
last = NullChar; |
|||
length = 0; |
|||
} |
|||
else |
|||
{ |
|||
if (length > 1) |
|||
{ |
|||
sb.Append(c); |
|||
} |
|||
else if (length == 0) |
|||
{ |
|||
last = c; |
|||
} |
|||
else |
|||
{ |
|||
sb.Append(char.ToUpperInvariant(last)); |
|||
sb.Append(c); |
|||
|
|||
last = NullChar; |
|||
} |
|||
|
|||
length++; |
|||
} |
|||
} |
|||
|
|||
if (last != NullChar) |
|||
{ |
|||
sb.Append(char.ToUpperInvariant(last)); |
|||
} |
|||
|
|||
return sb.ToString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Squidex; |
|||
|
|||
public sealed class FixtureModel |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string Label { get; set; } |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
#pragma warning disable |
|||
// Auto-generated code |
|||
namespace Squidex.EntityFramework.TestHelpers; |
|||
|
|||
[CollectionDefinition("Postgres{{Name}}")] |
|||
public sealed class Postgres{{Name}}FixtureCollection : ICollectionFixture<Postgres{{Name}}Fixture> |
|||
{ |
|||
} |
|||
|
|||
public sealed class Postgres{{Name}}Fixture() : PostgresFixture("squidex-postgres-{{Label}}") |
|||
{ |
|||
} |
|||
|
|||
[CollectionDefinition("MySql{{Name}}")] |
|||
public sealed class MySql{{Name}}FixtureCollection : ICollectionFixture<MySql{{Name}}Fixture> |
|||
{ |
|||
} |
|||
|
|||
public sealed class MySql{{Name}}Fixture() : MySqlFixture("squidex-mysql-{{Label}}") |
|||
{ |
|||
} |
|||
|
|||
[CollectionDefinition("SqlServer{{Name}}")] |
|||
public sealed class SqlServer{{Name}}FixtureCollection : ICollectionFixture<SqlServer{{Name}}Fixture> |
|||
{ |
|||
} |
|||
|
|||
public sealed class SqlServer{{Name}}Fixture() : SqlServerFixture("squidex-mssql-{{Label}}") |
|||
{ |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
#pragma warning disable |
|||
// Auto-generated code |
|||
using Squidex.EntityFramework.TestHelpers; |
|||
|
|||
namespace {{classNamespace}}; |
|||
|
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("Postgres")] |
|||
public class Postgres{{className}}(PostgresFixture fixture) : {{baseName}}<TestDbContextPostgres>(fixture) |
|||
{ |
|||
} |
|||
|
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("MySql")] |
|||
public class MySql{{className}}(MySqlFixture fixture) : {{baseName}}<TestDbContextMySql>(fixture) |
|||
{ |
|||
} |
|||
|
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("SqlServer")] |
|||
public class SqlServer{{className}}(SqlServerFixture fixture) : {{baseName}}<TestDbContextSqlServer>(fixture) |
|||
{ |
|||
} |
|||
@ -1,77 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Diagnostics; |
|||
using System.Text; |
|||
using HandlebarsDotNet; |
|||
using Microsoft.CodeAnalysis; |
|||
using Microsoft.CodeAnalysis.CSharp; |
|||
using Microsoft.CodeAnalysis.CSharp.Syntax; |
|||
using Microsoft.CodeAnalysis.Text; |
|||
|
|||
namespace Squidex.Data.Tests.CodeGenerator; |
|||
|
|||
[Generator] |
|||
public class TestGenerator : IIncrementalGenerator |
|||
{ |
|||
public void Initialize(IncrementalGeneratorInitializationContext context) |
|||
{ |
|||
var templateStream = typeof(TestGenerator).Assembly.GetManifestResourceStream("Squidex.Template.handlebar")!; |
|||
var templateText = new StreamReader(templateStream).ReadToEnd(); |
|||
|
|||
var template = Handlebars.Compile(templateText); |
|||
|
|||
static TemplateModel? Transform(GeneratorSyntaxContext ctx) |
|||
{ |
|||
var classSyntax = (ClassDeclarationSyntax)ctx.Node; |
|||
|
|||
var className = classSyntax.Identifier.Text; |
|||
if (!className.StartsWith("EF", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (!classSyntax.Modifiers.Any(x => x.IsKind(SyntaxKind.AbstractKeyword))) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (classSyntax.TypeParameterList == null || |
|||
classSyntax.TypeParameterList.Parameters.Count != 1 || |
|||
classSyntax.TypeParameterList.Parameters[0].Identifier.Text != "TContext") |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var namespaceDeclaration = |
|||
classSyntax.Ancestors() |
|||
.OfType<BaseNamespaceDeclarationSyntax>().First(); |
|||
|
|||
return new TemplateModel |
|||
{ |
|||
BaseName = classSyntax.Identifier.Text, |
|||
ClassName = classSyntax.Identifier.Text.Substring(2), |
|||
ClassNamespace = namespaceDeclaration.Name.ToString(), |
|||
}; |
|||
} |
|||
|
|||
var fieldDeclarations = context.SyntaxProvider.CreateSyntaxProvider( |
|||
static (node, _) => |
|||
{ |
|||
return node is ClassDeclarationSyntax; |
|||
}, |
|||
static (ctx, _) => Transform(ctx)) |
|||
.Where(x => x != null); |
|||
|
|||
context.RegisterSourceOutput(fieldDeclarations, (context, model) => |
|||
{ |
|||
var source = template(model); |
|||
|
|||
context.AddSource($"{model!.BaseName}_Tests.cs", SourceText.From(source, Encoding.UTF8)); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
#pragma warning disable |
|||
// Auto-generated code |
|||
using Squidex.EntityFramework.TestHelpers; |
|||
{{#if HasContentContext}} |
|||
using Squidex.Providers.MySql.Content; |
|||
using Squidex.Providers.Postgres.Content; |
|||
using Squidex.Providers.SqlServer.Content; |
|||
{{/if}} |
|||
|
|||
namespace {{classNamespace}}; |
|||
|
|||
{{#if HasContentContext}} |
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("Postgres{{CollectionSuffix}}")] |
|||
public class Postgres{{className}}(Postgres{{CollectionSuffix}}Fixture fixture) : {{baseName}}<TestDbContextPostgres, PostgresContentDbContext>(fixture) |
|||
{ |
|||
} |
|||
|
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("MySql{{CollectionSuffix}}")] |
|||
public class MySql{{className}}(MySql{{CollectionSuffix}}Fixture fixture) : {{baseName}}<TestDbContextMySql, MySqlContentDbContext>(fixture) |
|||
{ |
|||
} |
|||
|
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("SqlServer{{CollectionSuffix}}")] |
|||
public class SqlServer{{className}}(SqlServer{{CollectionSuffix}}Fixture fixture) : {{baseName}}<TestDbContextSqlServer, SqlServerContentDbContext>(fixture) |
|||
{ |
|||
} |
|||
{{else}} |
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("Postgres{{CollectionSuffix}}")] |
|||
public class Postgres{{className}}(Postgres{{CollectionSuffix}}Fixture fixture) : {{baseName}}<TestDbContextPostgres>(fixture) |
|||
{ |
|||
} |
|||
|
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("MySql{{CollectionSuffix}}")] |
|||
public class MySql{{className}}(MySql{{CollectionSuffix}}Fixture fixture) : {{baseName}}<TestDbContextMySql>(fixture) |
|||
{ |
|||
} |
|||
|
|||
[Trait("Category", "TestContainer")] |
|||
[Collection("SqlServer{{CollectionSuffix}}")] |
|||
public class SqlServer{{className}}(SqlServer{{CollectionSuffix}}Fixture fixture) : {{baseName}}<TestDbContextSqlServer>(fixture) |
|||
{ |
|||
} |
|||
{{/if}} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue