diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs index b296218cfbb2..b7ea7d490a2c 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs @@ -3,13 +3,16 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NPoco; +using NPoco.DatabaseTypes; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Actions; using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Infrastructure.Migrations.Upgrade; +using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Infrastructure.Persistence.Dtos; +using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.Migrations.Install; @@ -19,6 +22,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install; /// internal sealed class DatabaseDataCreator { +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. internal const string EditorGroupAlias = "editor"; @@ -95,6 +99,7 @@ internal sealed class DatabaseDataCreator private readonly IOptionsMonitor _installDefaultDataSettings; private readonly ILogger _logger; private readonly IUmbracoVersion _umbracoVersion; + private readonly IPocoDataFactory _pocoDataFactory; /// /// Initializes a new instance of the class. @@ -113,6 +118,7 @@ public DatabaseDataCreator( _logger = logger; _umbracoVersion = umbracoVersion; _installDefaultDataSettings = installDefaultDataSettings; + _pocoDataFactory = ((Database)database).PocoDataFactory; } /// @@ -124,82 +130,83 @@ public void InitializeBaseData(string tableName) { _logger.LogInformation("Creating data in {TableName}", tableName); - if (tableName.Equals(Constants.DatabaseSchema.Tables.Node)) + if (tableName.Equals(NodeDto.TableName)) { CreateNodeData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.Lock)) + if (tableName.Equals(LockDto.TableName)) { CreateLockData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.ContentType)) + if (tableName.Equals(ContentTypeDto.TableName)) { CreateContentTypeData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.User)) + if (tableName.Equals(UserDto.TableName)) { CreateUserData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.UserGroup)) + if (tableName.Equals(UserGroupDto.TableName)) { CreateUserGroupData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.UserGroup2Permission)) + if (tableName.Equals(UserGroup2PermissionDto.TableName)) { CreateUserGroup2PermissionData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.User2UserGroup)) + if (tableName.Equals(User2UserGroupDto.TableName)) { CreateUser2UserGroupData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.UserGroup2App)) + if (tableName.Equals(UserGroup2AppDto.TableName)) { CreateUserGroup2AppData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.PropertyTypeGroup)) + if (tableName.Equals(PropertyTypeGroupDto.TableName)) { CreatePropertyTypeGroupData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.PropertyType)) + if (tableName.Equals(PropertyTypeDto.TableName)) { CreatePropertyTypeData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.Language)) + if (tableName.Equals(LanguageDto.TableName)) { CreateLanguageData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.ContentChildType)) + // This was Constants.DatabaseSchema.Tables.ContentChildType, but the table name in database is: cmsContentTypeAllowedContentType + if (tableName.Equals(ContentTypeAllowedContentTypeDto.TableName)) { - CreateContentChildTypeData(); + CreateContentTypeAllowedContentType(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.DataType)) + if (tableName.Equals(DataTypeDto.TableName)) { CreateDataTypeData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.RelationType)) + if (tableName.Equals(RelationTypeDto.TableName)) { CreateRelationTypeData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.KeyValue)) + if (tableName.Equals(KeyValueDto.TableName)) { CreateKeyValueData(); } - if (tableName.Equals(Constants.DatabaseSchema.Tables.LogViewerQuery)) + if (tableName.Equals(LogViewerQueryDto.TableName)) { CreateLogViewerQueryData(); } @@ -222,10 +229,7 @@ private void CreateUserGroup2PermissionData() { foreach (var permission in permissions) { - _database.Insert( - Constants.DatabaseSchema.Tables.UserGroup2Permission, - "id", - false, + Insert( new UserGroup2PermissionDto { Id = i++, @@ -267,15 +271,10 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, uniqueId, - nodeDto, - Constants.DatabaseSchema.Tables.Node, - "id"); + nodeDto); } - _database.Insert( - Constants.DatabaseSchema.Tables.Node, - "id", - false, + Insert( new NodeDto { NodeId = -1, @@ -290,78 +289,79 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) NodeObjectType = Constants.ObjectTypes.SystemRoot, CreateDate = DateTime.UtcNow, }); - _database.Insert( - Constants.DatabaseSchema.Tables.Node, - "id", - false, - new NodeDto - { - NodeId = Constants.System.RecycleBinContent, - Trashed = false, - ParentId = -1, - UserId = -1, - Level = 0, - Path = "-1,-20", - SortOrder = 0, - UniqueId = Constants.System.RecycleBinContentKey, - Text = "Recycle Bin", - NodeObjectType = Constants.ObjectTypes.ContentRecycleBin, - CreateDate = DateTime.UtcNow, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.Node, - "id", - false, - new NodeDto - { - NodeId = Constants.System.RecycleBinMedia, - Trashed = false, - ParentId = -1, - UserId = -1, - Level = 0, - Path = "-1,-21", - SortOrder = 0, - UniqueId = Constants.System.RecycleBinMediaKey, - Text = "Recycle Bin", - NodeObjectType = Constants.ObjectTypes.MediaRecycleBin, - CreateDate = DateTime.UtcNow, - }); + + Insert(new NodeDto + { + NodeId = Constants.System.RecycleBinContent, + Trashed = false, + ParentId = -1, + UserId = -1, + Level = 0, + Path = "-1,-20", + SortOrder = 0, + UniqueId = Constants.System.RecycleBinContentKey, + Text = "Recycle Bin", + NodeObjectType = Constants.ObjectTypes.ContentRecycleBin, + CreateDate = DateTime.UtcNow, + }); + + Insert(new NodeDto + { + NodeId = Constants.System.RecycleBinMedia, + Trashed = false, + ParentId = -1, + UserId = -1, + Level = 0, + Path = "-1,-21", + SortOrder = 0, + UniqueId = Constants.System.RecycleBinMediaKey, + Text = "Recycle Bin", + NodeObjectType = Constants.ObjectTypes.MediaRecycleBin, + CreateDate = DateTime.UtcNow, + }); InsertDataTypeNodeDto( Constants.DataTypes.LabelString, 35, Constants.DataTypes.Guids.LabelString, "Label (string)"); + InsertDataTypeNodeDto( Constants.DataTypes.LabelInt, 36, Constants.DataTypes.Guids.LabelInt, "Label (integer)"); + InsertDataTypeNodeDto( Constants.DataTypes.LabelBigint, 36, Constants.DataTypes.Guids.LabelBigInt, "Label (bigint)"); + InsertDataTypeNodeDto( Constants.DataTypes.LabelDateTime, 37, Constants.DataTypes.Guids.LabelDateTime, "Label (datetime)"); + InsertDataTypeNodeDto( Constants.DataTypes.LabelTime, 38, Constants.DataTypes.Guids.LabelTime, "Label (time)"); + InsertDataTypeNodeDto( Constants.DataTypes.LabelDecimal, 39, Constants.DataTypes.Guids.LabelDecimal, "Label (decimal)"); + InsertDataTypeNodeDto( Constants.DataTypes.LabelBytes, 40, Constants.DataTypes.Guids.LabelBytes, "Label (bytes)"); + InsertDataTypeNodeDto( Constants.DataTypes.LabelPixels, 41, @@ -384,9 +384,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Upload File", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.UploadVideo, @@ -403,9 +402,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Upload Video", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.UploadAudio, @@ -422,9 +420,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Upload Audio", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.UploadArticle, @@ -441,9 +438,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Upload Article", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.UploadVectorGraphics, @@ -460,9 +456,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Upload Vector Graphics", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.Textarea, @@ -479,9 +474,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Textarea", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.Textstring, @@ -498,9 +492,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Textstring", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.RichtextEditor, @@ -517,9 +510,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Richtext editor", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.Numeric, @@ -536,9 +528,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Numeric", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.Checkbox, @@ -555,9 +546,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "True/false", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.CheckboxList, @@ -574,9 +564,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Checkbox list", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.Dropdown, @@ -593,9 +582,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.DatePicker, @@ -612,9 +600,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.Radiobox, @@ -631,9 +618,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.DropdownMultiple, @@ -650,9 +636,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.ApprovedColor, @@ -669,9 +654,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.DatePickerWithTime, @@ -688,9 +672,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.ListViewContent, @@ -707,9 +690,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.ListViewMedia, @@ -726,9 +708,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.Tags, @@ -745,9 +726,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Tags", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.ImageCropper, @@ -764,9 +744,7 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Image Cropper", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); // New UDI pickers with newer Ids ConditionalInsert( @@ -785,9 +763,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Content Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.MemberPicker, @@ -804,9 +781,7 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Member Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, @@ -824,9 +799,7 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Multi URL Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, @@ -844,9 +817,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.MediaPicker3Multiple, @@ -863,9 +835,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Multiple Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.MediaPicker3SingleImage, @@ -882,9 +853,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Image Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.MediaPicker3MultipleImages, @@ -901,9 +871,8 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Multiple Image Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); + ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, Constants.DataTypes.Guids.DateTimePickerWithTimeZone, @@ -920,9 +889,7 @@ void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) Text = "Date Time Picker (with time zone)", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); } private void CreateNodeDataForMediaTypes() @@ -944,9 +911,7 @@ private void CreateNodeDataForMediaTypes() Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, @@ -964,9 +929,7 @@ private void CreateNodeDataForMediaTypes() Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, @@ -984,9 +947,7 @@ private void CreateNodeDataForMediaTypes() Text = Constants.Conventions.MediaTypes.File, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, @@ -1004,9 +965,7 @@ private void CreateNodeDataForMediaTypes() Text = Constants.Conventions.MediaTypes.Video, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, @@ -1024,9 +983,7 @@ private void CreateNodeDataForMediaTypes() Text = Constants.Conventions.MediaTypes.Audio, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, @@ -1044,9 +1001,7 @@ private void CreateNodeDataForMediaTypes() Text = Constants.Conventions.MediaTypes.Article, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, @@ -1064,9 +1019,7 @@ private void CreateNodeDataForMediaTypes() Text = "Vector Graphics (SVG)", NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); } private void CreateNodeDataForMemberTypes() @@ -1087,33 +1040,31 @@ private void CreateNodeDataForMemberTypes() Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = Constants.ObjectTypes.MemberType, CreateDate = DateTime.UtcNow, - }, - Constants.DatabaseSchema.Tables.Node, - "id"); + }); } private void CreateLockData() { // all lock objects - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.Servers, Name = "Servers" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.ContentTypes, Name = "ContentTypes" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.ContentTree, Name = "ContentTree" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MediaTypes, Name = "MediaTypes" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MediaTree, Name = "MediaTree" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MemberTypes, Name = "MemberTypes" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MemberTree, Name = "MemberTree" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.Domains, Name = "Domains" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.KeyValues, Name = "KeyValues" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.Languages, Name = "Languages" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.ScheduledPublishing, Name = "ScheduledPublishing" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MainDom, Name = "MainDom" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.WebhookRequest, Name = "WebhookRequest" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.WebhookLogs, Name = "WebhookLogs" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.LongRunningOperations, Name = "LongRunningOperations" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.DocumentUrls, Name = "DocumentUrls" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.DistributedJobs, Name = "DistributedJobs" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.CacheVersion, Name = "CacheVersion" }); - _database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.DocumentUrlAliases, Name = "DocumentUrlAliases" }); + Insert(new LockDto { Id = Constants.Locks.Servers, Name = "Servers" }); + Insert(new LockDto { Id = Constants.Locks.ContentTypes, Name = "ContentTypes" }); + Insert(new LockDto { Id = Constants.Locks.ContentTree, Name = "ContentTree" }); + Insert(new LockDto { Id = Constants.Locks.MediaTypes, Name = "MediaTypes" }); + Insert(new LockDto { Id = Constants.Locks.MediaTree, Name = "MediaTree" }); + Insert(new LockDto { Id = Constants.Locks.MemberTypes, Name = "MemberTypes" }); + Insert(new LockDto { Id = Constants.Locks.MemberTree, Name = "MemberTree" }); + Insert(new LockDto { Id = Constants.Locks.Domains, Name = "Domains" }); + Insert(new LockDto { Id = Constants.Locks.KeyValues, Name = "KeyValues" }); + Insert(new LockDto { Id = Constants.Locks.Languages, Name = "Languages" }); + Insert(new LockDto { Id = Constants.Locks.ScheduledPublishing, Name = "ScheduledPublishing" }); + Insert(new LockDto { Id = Constants.Locks.MainDom, Name = "MainDom" }); + Insert(new LockDto { Id = Constants.Locks.WebhookRequest, Name = "WebhookRequest" }); + Insert(new LockDto { Id = Constants.Locks.WebhookLogs, Name = "WebhookLogs" }); + Insert(new LockDto { Id = Constants.Locks.LongRunningOperations, Name = "LongRunningOperations" }); + Insert(new LockDto { Id = Constants.Locks.DocumentUrls, Name = "DocumentUrls" }); + Insert(new LockDto { Id = Constants.Locks.DistributedJobs, Name = "DistributedJobs" }); + Insert(new LockDto { Id = Constants.Locks.CacheVersion, Name = "CacheVersion" }); + Insert(new LockDto { Id = Constants.Locks.DocumentUrlAliases, Name = "DocumentUrlAliases" }); } private void CreateContentTypeData() @@ -1124,269 +1075,218 @@ private void CreateContentTypeData() // Media types. if (_database.Exists(1031)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 532, - NodeId = 1031, - Alias = Constants.Conventions.MediaTypes.Folder, - Icon = Constants.Icons.MediaFolder, - Thumbnail = Constants.Icons.MediaFolder, - AllowAtRoot = true, - Variations = (byte)ContentVariation.Nothing, - ListView = Constants.DataTypes.Guids.ListViewMediaGuid - }); + Insert(new ContentTypeDto + { + PrimaryKey = 532, + NodeId = 1031, + Alias = Constants.Conventions.MediaTypes.Folder, + Icon = Constants.Icons.MediaFolder, + Thumbnail = Constants.Icons.MediaFolder, + AllowAtRoot = true, + Variations = (byte)ContentVariation.Nothing, + ListView = Constants.DataTypes.Guids.ListViewMediaGuid + }); } if (_database.Exists(1032)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 533, - NodeId = 1032, - Alias = Constants.Conventions.MediaTypes.Image, - Icon = Constants.Icons.MediaImage, - Thumbnail = Constants.Icons.MediaImage, - AllowAtRoot = true, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new ContentTypeDto + { + PrimaryKey = 533, + NodeId = 1032, + Alias = Constants.Conventions.MediaTypes.Image, + Icon = Constants.Icons.MediaImage, + Thumbnail = Constants.Icons.MediaImage, + AllowAtRoot = true, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(1033)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 534, - NodeId = 1033, - Alias = Constants.Conventions.MediaTypes.File, - Icon = Constants.Icons.MediaFile, - Thumbnail = Constants.Icons.MediaFile, - AllowAtRoot = true, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new ContentTypeDto + { + PrimaryKey = 534, + NodeId = 1033, + Alias = Constants.Conventions.MediaTypes.File, + Icon = Constants.Icons.MediaFile, + Thumbnail = Constants.Icons.MediaFile, + AllowAtRoot = true, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(1034)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 540, - NodeId = 1034, - Alias = Constants.Conventions.MediaTypes.VideoAlias, - Icon = Constants.Icons.MediaVideo, - Thumbnail = Constants.Icons.MediaVideo, - AllowAtRoot = true, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new ContentTypeDto + { + PrimaryKey = 540, + NodeId = 1034, + Alias = Constants.Conventions.MediaTypes.VideoAlias, + Icon = Constants.Icons.MediaVideo, + Thumbnail = Constants.Icons.MediaVideo, + AllowAtRoot = true, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(1035)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 541, - NodeId = 1035, - Alias = Constants.Conventions.MediaTypes.AudioAlias, - Icon = Constants.Icons.MediaAudio, - Thumbnail = Constants.Icons.MediaAudio, - AllowAtRoot = true, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new ContentTypeDto + { + PrimaryKey = 541, + NodeId = 1035, + Alias = Constants.Conventions.MediaTypes.AudioAlias, + Icon = Constants.Icons.MediaAudio, + Thumbnail = Constants.Icons.MediaAudio, + AllowAtRoot = true, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(1036)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 542, - NodeId = 1036, - Alias = Constants.Conventions.MediaTypes.ArticleAlias, - Icon = Constants.Icons.MediaArticle, - Thumbnail = Constants.Icons.MediaArticle, - AllowAtRoot = true, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new ContentTypeDto + { + PrimaryKey = 542, + NodeId = 1036, + Alias = Constants.Conventions.MediaTypes.ArticleAlias, + Icon = Constants.Icons.MediaArticle, + Thumbnail = Constants.Icons.MediaArticle, + AllowAtRoot = true, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(1037)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 543, - NodeId = 1037, - Alias = Constants.Conventions.MediaTypes.VectorGraphicsAlias, - Icon = Constants.Icons.MediaVectorGraphics, - Thumbnail = Constants.Icons.MediaVectorGraphics, - AllowAtRoot = true, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new ContentTypeDto + { + PrimaryKey = 543, + NodeId = 1037, + Alias = Constants.Conventions.MediaTypes.VectorGraphicsAlias, + Icon = Constants.Icons.MediaVectorGraphics, + Thumbnail = Constants.Icons.MediaVectorGraphics, + AllowAtRoot = true, + Variations = (byte)ContentVariation.Nothing, + }); } // Member type. if (_database.Exists(1044)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentType, - "pk", - false, - new ContentTypeDto - { - PrimaryKey = 531, - NodeId = 1044, - Alias = Constants.Conventions.MemberTypes.DefaultAlias, - Icon = Constants.Icons.Member, - Thumbnail = Constants.Icons.Member, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new ContentTypeDto + { + PrimaryKey = 531, + NodeId = 1044, + Alias = Constants.Conventions.MemberTypes.DefaultAlias, + Icon = Constants.Icons.Member, + Thumbnail = Constants.Icons.Member, + Variations = (byte)ContentVariation.Nothing, + }); } } - private void CreateUserData() => _database.Insert( - Constants.DatabaseSchema.Tables.User, - "id", - false, - new UserDto - { - Id = Constants.Security.SuperUserId, - Key = Constants.Security.SuperUserKey, - Disabled = false, - NoConsole = false, - UserName = "Administrator", - Login = "admin", - Password = "default", - Email = string.Empty, - UserLanguage = "en-US", + private void CreateUserData() => Insert(new UserDto + { + Id = Constants.Security.SuperUserId, + Key = Constants.Security.SuperUserKey, + Disabled = false, + NoConsole = false, + UserName = "Administrator", + Login = "admin", + Password = "default", + Email = string.Empty, + UserLanguage = "en-US", + CreateDate = DateTime.UtcNow, + UpdateDate = DateTime.UtcNow, + }); + + private void CreateUserGroupData() + { + Insert(new UserGroupDto + { + Id = 1, + Key = Constants.Security.AdminGroupKey, + StartMediaId = -1, + StartContentId = -1, + Alias = Constants.Security.AdminGroupAlias, + Name = "Administrators", + Description = "Users with full access to all sections and functionality", CreateDate = DateTime.UtcNow, UpdateDate = DateTime.UtcNow, + Icon = "icon-medal", + HasAccessToAllLanguages = true, }); - private void CreateUserGroupData() - { - _database.Insert( - Constants.DatabaseSchema.Tables.UserGroup, - "id", - false, - new UserGroupDto - { - Id = 1, - Key = Constants.Security.AdminGroupKey, - StartMediaId = -1, - StartContentId = -1, - Alias = Constants.Security.AdminGroupAlias, - Name = "Administrators", - Description = "Users with full access to all sections and functionality", - CreateDate = DateTime.UtcNow, - UpdateDate = DateTime.UtcNow, - Icon = "icon-medal", - HasAccessToAllLanguages = true, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.UserGroup, - "id", - false, - new UserGroupDto - { - Id = 2, - Key = Constants.Security.WriterGroupKey, - StartMediaId = -1, - StartContentId = -1, - Alias = WriterGroupAlias, - Name = "Writers", - Description = "Users with permission to create and update but not publish content", - CreateDate = DateTime.UtcNow, - UpdateDate = DateTime.UtcNow, - Icon = "icon-edit", - HasAccessToAllLanguages = true, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.UserGroup, - "id", - false, - new UserGroupDto - { - Id = 3, - Key = Constants.Security.EditorGroupKey, - StartMediaId = -1, - StartContentId = -1, - Alias = EditorGroupAlias, - Name = "Editors", - Description = "Users with full permission to create, update and publish content", - CreateDate = DateTime.UtcNow, - UpdateDate = DateTime.UtcNow, - Icon = "icon-tools", - HasAccessToAllLanguages = true, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.UserGroup, - "id", - false, - new UserGroupDto - { - Id = 4, - Key = Constants.Security.TranslatorGroupKey, - StartMediaId = -1, - StartContentId = -1, - Alias = TranslatorGroupAlias, - Name = "Translators", - Description = "Users with permission to manage dictionary entries", - CreateDate = DateTime.UtcNow, - UpdateDate = DateTime.UtcNow, - Icon = "icon-globe", - HasAccessToAllLanguages = true, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.UserGroup, - "id", - false, - new UserGroupDto - { - Id = 5, - Key = Constants.Security.SensitiveDataGroupKey, - Alias = SensitiveDataGroupAlias, - Name = "Sensitive data", - Description = "Users with the specific permission to be able to manage properties and data marked as sensitive", - CreateDate = DateTime.UtcNow, - UpdateDate = DateTime.UtcNow, - Icon = "icon-lock", - HasAccessToAllLanguages = false, - }); + Insert(new UserGroupDto + { + Id = 2, + Key = Constants.Security.WriterGroupKey, + StartMediaId = -1, + StartContentId = -1, + Alias = WriterGroupAlias, + Name = "Writers", + Description = "Users with permission to create and update but not publish content", + CreateDate = DateTime.UtcNow, + UpdateDate = DateTime.UtcNow, + Icon = "icon-edit", + HasAccessToAllLanguages = true, + }); + + Insert(new UserGroupDto + { + Id = 3, + Key = Constants.Security.EditorGroupKey, + StartMediaId = -1, + StartContentId = -1, + Alias = EditorGroupAlias, + Name = "Editors", + Description = "Users with full permission to create, update and publish content", + CreateDate = DateTime.UtcNow, + UpdateDate = DateTime.UtcNow, + Icon = "icon-tools", + HasAccessToAllLanguages = true, + }); + + Insert(new UserGroupDto + { + Id = 4, + Key = Constants.Security.TranslatorGroupKey, + StartMediaId = -1, + StartContentId = -1, + Alias = TranslatorGroupAlias, + Name = "Translators", + Description = "Users with permission to manage dictionary entries", + CreateDate = DateTime.UtcNow, + UpdateDate = DateTime.UtcNow, + Icon = "icon-globe", + HasAccessToAllLanguages = true, + }); + + Insert(new UserGroupDto + { + Id = 5, + Key = Constants.Security.SensitiveDataGroupKey, + Alias = SensitiveDataGroupAlias, + Name = "Sensitive data", + Description = "Users with the specific permission to be able to manage properties and data marked as sensitive", + CreateDate = DateTime.UtcNow, + UpdateDate = DateTime.UtcNow, + Icon = "icon-lock", + HasAccessToAllLanguages = false, + }); } private void CreateUser2UserGroupData() { - _database.Insert(new User2UserGroupDto + Insert(new User2UserGroupDto { UserGroupId = 1, UserId = Constants.Security.SuperUserId, }); // add super to admins - _database.Insert(new User2UserGroupDto + + Insert(new User2UserGroupDto { UserGroupId = 5, UserId = Constants.Security.SuperUserId, @@ -1395,22 +1295,26 @@ private void CreateUser2UserGroupData() private void CreateUserGroup2AppData() { - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Content }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Packages }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Media }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Members }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Settings }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Users }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Forms }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Translation }); - - _database.Insert(new UserGroup2AppDto { UserGroupId = 2, AppAlias = Constants.Applications.Content }); - - _database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Content }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Media }); - _database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Forms }); - - _database.Insert(new UserGroup2AppDto { UserGroupId = 4, AppAlias = Constants.Applications.Translation }); + // UserGroupId = 1 + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Content }); + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Packages }); + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Media }); + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Members }); + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Settings }); + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Users }); + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Forms }); + Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Translation }); + + // UserGroupId = 2 + Insert(new UserGroup2AppDto { UserGroupId = 2, AppAlias = Constants.Applications.Content }); + + // UserGroupId = 3 + Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Content }); + Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Media }); + Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Forms }); + + // UserGroupId = 4 + Insert(new UserGroup2AppDto { UserGroupId = 4, AppAlias = Constants.Applications.Translation }); } private void CreatePropertyTypeGroupData() @@ -1421,122 +1325,94 @@ private void CreatePropertyTypeGroupData() // Media property groups. if (_database.Exists(1032)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyTypeGroup, - "id", - false, - new PropertyTypeGroupDto - { - Id = 3, - UniqueId = new Guid(Constants.PropertyTypeGroups.Image), - ContentTypeNodeId = 1032, - Text = "Image", - Alias = "image", - SortOrder = 1, - }); + Insert(new PropertyTypeGroupDto + { + Id = 3, + UniqueId = new Guid(Constants.PropertyTypeGroups.Image), + ContentTypeNodeId = 1032, + Text = "Image", + Alias = "image", + SortOrder = 1, + }); } if (_database.Exists(1033)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyTypeGroup, - "id", - false, - new PropertyTypeGroupDto - { - Id = 4, - UniqueId = new Guid(Constants.PropertyTypeGroups.File), - ContentTypeNodeId = 1033, - Text = "File", - Alias = "file", - SortOrder = 1, - }); + Insert(new PropertyTypeGroupDto + { + Id = 4, + UniqueId = new Guid(Constants.PropertyTypeGroups.File), + ContentTypeNodeId = 1033, + Text = "File", + Alias = "file", + SortOrder = 1, + }); } if (_database.Exists(1034)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyTypeGroup, - "id", - false, - new PropertyTypeGroupDto - { - Id = 52, - UniqueId = new Guid(Constants.PropertyTypeGroups.Video), - ContentTypeNodeId = 1034, - Text = "Video", - Alias = "video", - SortOrder = 1, - }); + Insert(new PropertyTypeGroupDto + { + Id = 52, + UniqueId = new Guid(Constants.PropertyTypeGroups.Video), + ContentTypeNodeId = 1034, + Text = "Video", + Alias = "video", + SortOrder = 1, + }); } if (_database.Exists(1035)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyTypeGroup, - "id", - false, - new PropertyTypeGroupDto - { - Id = 53, - UniqueId = new Guid(Constants.PropertyTypeGroups.Audio), - ContentTypeNodeId = 1035, - Text = "Audio", - Alias = "audio", - SortOrder = 1, - }); + Insert(new PropertyTypeGroupDto + { + Id = 53, + UniqueId = new Guid(Constants.PropertyTypeGroups.Audio), + ContentTypeNodeId = 1035, + Text = "Audio", + Alias = "audio", + SortOrder = 1, + }); } if (_database.Exists(1036)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyTypeGroup, - "id", - false, - new PropertyTypeGroupDto - { - Id = 54, - UniqueId = new Guid(Constants.PropertyTypeGroups.Article), - ContentTypeNodeId = 1036, - Text = "Article", - Alias = "article", - SortOrder = 1, - }); + Insert(new PropertyTypeGroupDto + { + Id = 54, + UniqueId = new Guid(Constants.PropertyTypeGroups.Article), + ContentTypeNodeId = 1036, + Text = "Article", + Alias = "article", + SortOrder = 1, + }); } if (_database.Exists(1037)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyTypeGroup, - "id", - false, - new PropertyTypeGroupDto - { - Id = 55, - UniqueId = new Guid(Constants.PropertyTypeGroups.VectorGraphics), - ContentTypeNodeId = 1037, - Text = "Vector Graphics", - Alias = "vectorGraphics", - SortOrder = 1, - }); + Insert(new PropertyTypeGroupDto + { + Id = 55, + UniqueId = new Guid(Constants.PropertyTypeGroups.VectorGraphics), + ContentTypeNodeId = 1037, + Text = "Vector Graphics", + Alias = "vectorGraphics", + SortOrder = 1, + }); } // Membership property group. if (_database.Exists(1044)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyTypeGroup, - "id", - false, - new PropertyTypeGroupDto - { - Id = 11, - UniqueId = new Guid(Constants.PropertyTypeGroups.Membership), - ContentTypeNodeId = 1044, - Text = Constants.Conventions.Member.StandardPropertiesGroupName, - Alias = Constants.Conventions.Member.StandardPropertiesGroupAlias, - SortOrder = 1, - }); + Insert(new PropertyTypeGroupDto + { + Id = 11, + UniqueId = new Guid(Constants.PropertyTypeGroups.Membership), + ContentTypeNodeId = 1044, + Text = Constants.Conventions.Member.StandardPropertiesGroupName, + Alias = Constants.Conventions.Member.StandardPropertiesGroupAlias, + SortOrder = 1, + }); } } @@ -1548,430 +1424,360 @@ private void CreatePropertyTypeData() // Media property types. if (_database.Exists(3)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 6, - UniqueId = new Guid("B646CA8F-E469-4FC2-A48A-D4DC1AA64A53"), - DataTypeId = Constants.DataTypes.ImageCropper, - ContentTypeId = 1032, - PropertyTypeGroupId = 3, - Alias = Constants.Conventions.Media.File, - Name = "Image", - SortOrder = 0, - Mandatory = true, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 7, - UniqueId = new Guid("A68D453B-1F62-44F4-9F71-0B6BBD43C355"), - DataTypeId = Constants.DataTypes.LabelPixels, - ContentTypeId = 1032, - PropertyTypeGroupId = 3, - Alias = Constants.Conventions.Media.Width, - Name = "Width", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 8, - UniqueId = new Guid("854087F6-648B-40ED-BC98-B8A9789E80B9"), - DataTypeId = Constants.DataTypes.LabelPixels, - ContentTypeId = 1032, - PropertyTypeGroupId = 3, - Alias = Constants.Conventions.Media.Height, - Name = "Height", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 9, - UniqueId = new Guid("BD4C5ACE-26E3-4A8B-AF1A-E8206A35FA07"), - DataTypeId = Constants.DataTypes.LabelBytes, - ContentTypeId = 1032, - PropertyTypeGroupId = 3, - Alias = Constants.Conventions.Media.Bytes, - Name = "File size", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 10, - UniqueId = new Guid("F7786FE8-724A-4ED0-B244-72546DB32A92"), - DataTypeId = Constants.DataTypes.LabelString, - ContentTypeId = 1032, - PropertyTypeGroupId = 3, - Alias = Constants.Conventions.Media.Extension, - Name = "File extension", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new PropertyTypeDto + { + Id = 6, + UniqueId = new Guid("B646CA8F-E469-4FC2-A48A-D4DC1AA64A53"), + DataTypeId = Constants.DataTypes.ImageCropper, + ContentTypeId = 1032, + PropertyTypeGroupId = 3, + Alias = Constants.Conventions.Media.File, + Name = "Image", + SortOrder = 0, + Mandatory = true, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 7, + UniqueId = new Guid("A68D453B-1F62-44F4-9F71-0B6BBD43C355"), + DataTypeId = Constants.DataTypes.LabelPixels, + ContentTypeId = 1032, + PropertyTypeGroupId = 3, + Alias = Constants.Conventions.Media.Width, + Name = "Width", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 8, + UniqueId = new Guid("854087F6-648B-40ED-BC98-B8A9789E80B9"), + DataTypeId = Constants.DataTypes.LabelPixels, + ContentTypeId = 1032, + PropertyTypeGroupId = 3, + Alias = Constants.Conventions.Media.Height, + Name = "Height", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 9, + UniqueId = new Guid("BD4C5ACE-26E3-4A8B-AF1A-E8206A35FA07"), + DataTypeId = Constants.DataTypes.LabelBytes, + ContentTypeId = 1032, + PropertyTypeGroupId = 3, + Alias = Constants.Conventions.Media.Bytes, + Name = "File size", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 10, + UniqueId = new Guid("F7786FE8-724A-4ED0-B244-72546DB32A92"), + DataTypeId = Constants.DataTypes.LabelString, + ContentTypeId = 1032, + PropertyTypeGroupId = 3, + Alias = Constants.Conventions.Media.Extension, + Name = "File extension", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(4)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 24, - UniqueId = new Guid("A0FB68F3-F427-47A6-AFCE-536FFA5B64E9"), - DataTypeId = Constants.DataTypes.Upload, - ContentTypeId = 1033, - PropertyTypeGroupId = 4, - Alias = Constants.Conventions.Media.File, - Name = "File", - SortOrder = 0, - Mandatory = true, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 25, - UniqueId = new Guid("3531C0A3-4E0A-4324-A621-B9D3822B071F"), - DataTypeId = Constants.DataTypes.LabelString, - ContentTypeId = 1033, - PropertyTypeGroupId = 4, - Alias = Constants.Conventions.Media.Extension, - Name = "File extension", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 26, - UniqueId = new Guid("F9527050-59BC-43E4-8FA8-1658D1319FF5"), - DataTypeId = Constants.DataTypes.LabelBytes, - ContentTypeId = 1033, - PropertyTypeGroupId = 4, - Alias = Constants.Conventions.Media.Bytes, - Name = "File size", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new PropertyTypeDto + { + Id = 24, + UniqueId = new Guid("A0FB68F3-F427-47A6-AFCE-536FFA5B64E9"), + DataTypeId = Constants.DataTypes.Upload, + ContentTypeId = 1033, + PropertyTypeGroupId = 4, + Alias = Constants.Conventions.Media.File, + Name = "File", + SortOrder = 0, + Mandatory = true, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 25, + UniqueId = new Guid("3531C0A3-4E0A-4324-A621-B9D3822B071F"), + DataTypeId = Constants.DataTypes.LabelString, + ContentTypeId = 1033, + PropertyTypeGroupId = 4, + Alias = Constants.Conventions.Media.Extension, + Name = "File extension", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 26, + UniqueId = new Guid("F9527050-59BC-43E4-8FA8-1658D1319FF5"), + DataTypeId = Constants.DataTypes.LabelBytes, + ContentTypeId = 1033, + PropertyTypeGroupId = 4, + Alias = Constants.Conventions.Media.Bytes, + Name = "File size", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(52)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 40, - UniqueId = new Guid("BED8AB97-D85F-44D2-A8B9-AEF6893F9610"), - DataTypeId = Constants.DataTypes.UploadVideo, - ContentTypeId = 1034, - PropertyTypeGroupId = 52, - Alias = Constants.Conventions.Media.File, - Name = "Video", - SortOrder = 0, - Mandatory = true, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 41, - UniqueId = new Guid("EDD2B3FD-1E57-4E57-935E-096DEFCCDC9B"), - DataTypeId = Constants.DataTypes.LabelString, - ContentTypeId = 1034, - PropertyTypeGroupId = 52, - Alias = Constants.Conventions.Media.Extension, - Name = "File extension", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 42, - UniqueId = new Guid("180EEECF-1F00-409E-8234-BBA967E08B0A"), - DataTypeId = Constants.DataTypes.LabelBytes, - ContentTypeId = 1034, - PropertyTypeGroupId = 52, - Alias = Constants.Conventions.Media.Bytes, - Name = "File size", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new PropertyTypeDto + { + Id = 40, + UniqueId = new Guid("BED8AB97-D85F-44D2-A8B9-AEF6893F9610"), + DataTypeId = Constants.DataTypes.UploadVideo, + ContentTypeId = 1034, + PropertyTypeGroupId = 52, + Alias = Constants.Conventions.Media.File, + Name = "Video", + SortOrder = 0, + Mandatory = true, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 41, + UniqueId = new Guid("EDD2B3FD-1E57-4E57-935E-096DEFCCDC9B"), + DataTypeId = Constants.DataTypes.LabelString, + ContentTypeId = 1034, + PropertyTypeGroupId = 52, + Alias = Constants.Conventions.Media.Extension, + Name = "File extension", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 42, + UniqueId = new Guid("180EEECF-1F00-409E-8234-BBA967E08B0A"), + DataTypeId = Constants.DataTypes.LabelBytes, + ContentTypeId = 1034, + PropertyTypeGroupId = 52, + Alias = Constants.Conventions.Media.Bytes, + Name = "File size", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(53)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 43, - UniqueId = new Guid("1F48D730-F174-4684-AFAD-A335E59D84A0"), - DataTypeId = Constants.DataTypes.UploadAudio, - ContentTypeId = 1035, - PropertyTypeGroupId = 53, - Alias = Constants.Conventions.Media.File, - Name = "Audio", - SortOrder = 0, - Mandatory = true, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 44, - UniqueId = new Guid("1BEE433F-A21A-4031-8E03-AF01BB8D2DE9"), - DataTypeId = Constants.DataTypes.LabelString, - ContentTypeId = 1035, - PropertyTypeGroupId = 53, - Alias = Constants.Conventions.Media.Extension, - Name = "File extension", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 45, - UniqueId = new Guid("3CBF538A-29AB-4317-A9EB-BBCDF1A54260"), - DataTypeId = Constants.DataTypes.LabelBytes, - ContentTypeId = 1035, - PropertyTypeGroupId = 53, - Alias = Constants.Conventions.Media.Bytes, - Name = "File size", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new PropertyTypeDto + { + Id = 43, + UniqueId = new Guid("1F48D730-F174-4684-AFAD-A335E59D84A0"), + DataTypeId = Constants.DataTypes.UploadAudio, + ContentTypeId = 1035, + PropertyTypeGroupId = 53, + Alias = Constants.Conventions.Media.File, + Name = "Audio", + SortOrder = 0, + Mandatory = true, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 44, + UniqueId = new Guid("1BEE433F-A21A-4031-8E03-AF01BB8D2DE9"), + DataTypeId = Constants.DataTypes.LabelString, + ContentTypeId = 1035, + PropertyTypeGroupId = 53, + Alias = Constants.Conventions.Media.Extension, + Name = "File extension", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 45, + UniqueId = new Guid("3CBF538A-29AB-4317-A9EB-BBCDF1A54260"), + DataTypeId = Constants.DataTypes.LabelBytes, + ContentTypeId = 1035, + PropertyTypeGroupId = 53, + Alias = Constants.Conventions.Media.Bytes, + Name = "File size", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(54)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 46, - UniqueId = new Guid("E5C8C2D0-2D82-4F01-B53A-45A1D1CBF19C"), - DataTypeId = Constants.DataTypes.UploadArticle, - ContentTypeId = 1036, - PropertyTypeGroupId = 54, - Alias = Constants.Conventions.Media.File, - Name = "Article", - SortOrder = 0, - Mandatory = true, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 47, - UniqueId = new Guid("EF1B4AF7-36DE-45EB-8C18-A2DE07319227"), - DataTypeId = Constants.DataTypes.LabelString, - ContentTypeId = 1036, - PropertyTypeGroupId = 54, - Alias = Constants.Conventions.Media.Extension, - Name = "File extension", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 48, - UniqueId = new Guid("AAB7D00C-7209-4337-BE3F-A4421C8D79A0"), - DataTypeId = Constants.DataTypes.LabelBytes, - ContentTypeId = 1036, - PropertyTypeGroupId = 54, - Alias = Constants.Conventions.Media.Bytes, - Name = "File size", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new PropertyTypeDto + { + Id = 46, + UniqueId = new Guid("E5C8C2D0-2D82-4F01-B53A-45A1D1CBF19C"), + DataTypeId = Constants.DataTypes.UploadArticle, + ContentTypeId = 1036, + PropertyTypeGroupId = 54, + Alias = Constants.Conventions.Media.File, + Name = "Article", + SortOrder = 0, + Mandatory = true, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 47, + UniqueId = new Guid("EF1B4AF7-36DE-45EB-8C18-A2DE07319227"), + DataTypeId = Constants.DataTypes.LabelString, + ContentTypeId = 1036, + PropertyTypeGroupId = 54, + Alias = Constants.Conventions.Media.Extension, + Name = "File extension", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 48, + UniqueId = new Guid("AAB7D00C-7209-4337-BE3F-A4421C8D79A0"), + DataTypeId = Constants.DataTypes.LabelBytes, + ContentTypeId = 1036, + PropertyTypeGroupId = 54, + Alias = Constants.Conventions.Media.Bytes, + Name = "File size", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); } if (_database.Exists(55)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 49, - UniqueId = new Guid("E2A2BDF2-971B-483E-95A1-4104CC06AF26"), - DataTypeId = Constants.DataTypes.UploadVectorGraphics, - ContentTypeId = 1037, - PropertyTypeGroupId = 55, - Alias = Constants.Conventions.Media.File, - Name = "Vector Graphics", - SortOrder = 0, - Mandatory = true, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 50, - UniqueId = new Guid("0F25A89E-2EB7-49BC-A7B4-759A7E4C69F2"), - DataTypeId = Constants.DataTypes.LabelString, - ContentTypeId = 1037, - PropertyTypeGroupId = 55, - Alias = Constants.Conventions.Media.Extension, - Name = "File extension", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 51, - UniqueId = new Guid("09A07AFF-861D-4769-A2B0-C165EBD43D39"), - DataTypeId = Constants.DataTypes.LabelBytes, - ContentTypeId = 1037, - PropertyTypeGroupId = 55, - Alias = Constants.Conventions.Media.Bytes, - Name = "File size", - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new PropertyTypeDto + { + Id = 49, + UniqueId = new Guid("E2A2BDF2-971B-483E-95A1-4104CC06AF26"), + DataTypeId = Constants.DataTypes.UploadVectorGraphics, + ContentTypeId = 1037, + PropertyTypeGroupId = 55, + Alias = Constants.Conventions.Media.File, + Name = "Vector Graphics", + SortOrder = 0, + Mandatory = true, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 50, + UniqueId = new Guid("0F25A89E-2EB7-49BC-A7B4-759A7E4C69F2"), + DataTypeId = Constants.DataTypes.LabelString, + ContentTypeId = 1037, + PropertyTypeGroupId = 55, + Alias = Constants.Conventions.Media.Extension, + Name = "File extension", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); + + Insert(new PropertyTypeDto + { + Id = 51, + UniqueId = new Guid("09A07AFF-861D-4769-A2B0-C165EBD43D39"), + DataTypeId = Constants.DataTypes.LabelBytes, + ContentTypeId = 1037, + PropertyTypeGroupId = 55, + Alias = Constants.Conventions.Media.Bytes, + Name = "File size", + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); } // Membership property types. if (_database.Exists(11)) { - _database.Insert( - Constants.DatabaseSchema.Tables.PropertyType, - "id", - false, - new PropertyTypeDto - { - Id = 28, - UniqueId = new Guid("70F24C26-1C0E-4053-BD8E-E9E6E4EC4C01"), - DataTypeId = Constants.DataTypes.Textarea, - ContentTypeId = 1044, - PropertyTypeGroupId = 11, - Alias = Constants.Conventions.Member.Comments, - Name = Constants.Conventions.Member.CommentsLabel, - SortOrder = 0, - Mandatory = false, - ValidationRegExp = null, - Description = null, - Variations = (byte)ContentVariation.Nothing, - }); + Insert(new PropertyTypeDto + { + Id = 28, + UniqueId = new Guid("70F24C26-1C0E-4053-BD8E-E9E6E4EC4C01"), + DataTypeId = Constants.DataTypes.Textarea, + ContentTypeId = 1044, + PropertyTypeGroupId = 11, + Alias = Constants.Conventions.Member.Comments, + Name = Constants.Conventions.Member.CommentsLabel, + SortOrder = 0, + Mandatory = false, + ValidationRegExp = null, + Description = null, + Variations = (byte)ContentVariation.Nothing, + }); } } @@ -1993,14 +1799,13 @@ private void CreateLanguageData() continue; } - var dto = new LanguageDto + Insert(new LanguageDto { Id = id, IsoCode = culture.Name, CultureName = culture.EnglishName, IsDefault = isDefault, - }; - _database.Insert(Constants.DatabaseSchema.Tables.Language, "id", false, dto); + }); isDefault = false; id += 1; } @@ -2013,9 +1818,13 @@ private void CreateLanguageData() ConditionalInsert( Constants.Configuration.NamedOptions.InstallDefaultData.Languages, culture.Name, - new LanguageDto { Id = 1, IsoCode = culture.Name, CultureName = culture.EnglishName, IsDefault = true }, - Constants.DatabaseSchema.Tables.Language, - "id"); + new LanguageDto + { + Id = 1, + IsoCode = culture.Name, + CultureName = culture.EnglishName, + IsDefault = true + }); } } } @@ -2035,7 +1844,7 @@ private bool TryCreateCulture(string isoCode, [NotNullWhen(true)] out CultureInf } } - private void CreateContentChildTypeData() + private void CreateContentTypeAllowedContentType() { // Insert data if the corresponding Node records exist (which may or may not have been created depending on configuration // of media types to create). @@ -2044,21 +1853,13 @@ private void CreateContentChildTypeData() return; } - _database.Insert( - Constants.DatabaseSchema.Tables.ContentChildType, - "Id", - false, - new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1031 }); + Insert(new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1031 }); for (var i = 1032; i <= 1037; i++) { if (_database.Exists(i)) { - _database.Insert( - Constants.DatabaseSchema.Tables.ContentChildType, - "Id", - false, - new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = i }); + Insert(new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = i }); } } } @@ -2076,7 +1877,7 @@ void InsertDataTypeDto(int id, string editorAlias, string editorUiAlias, string if (_database.Exists(id)) { - _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, dataTypeDto); + Insert(dataTypeDto); } } @@ -2093,93 +1894,69 @@ string GridCollectionView(string collectionViewType) => // of data types to create). if (_database.Exists(Constants.DataTypes.Boolean)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.Boolean, - EditorAlias = Constants.PropertyEditors.Aliases.Boolean, - EditorUiAlias = "Umb.PropertyEditorUi.Toggle", - DbType = "Integer", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.Boolean, + EditorAlias = Constants.PropertyEditors.Aliases.Boolean, + EditorUiAlias = "Umb.PropertyEditorUi.Toggle", + DbType = "Integer", + }); } if (_database.Exists(-51)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = -51, - EditorAlias = Constants.PropertyEditors.Aliases.Integer, - EditorUiAlias = "Umb.PropertyEditorUi.Integer", - DbType = "Integer", - }); + Insert(new DataTypeDto + { + NodeId = -51, + EditorAlias = Constants.PropertyEditors.Aliases.Integer, + EditorUiAlias = "Umb.PropertyEditorUi.Integer", + DbType = "Integer", + }); } if (_database.Exists(Constants.DataTypes.RichtextEditor)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.RichtextEditor, - EditorAlias = Constants.PropertyEditors.Aliases.RichText, - EditorUiAlias = "Umb.PropertyEditorUi.Tiptap", - DbType = "Ntext", - Configuration = "{\"extensions\": [\"Umb.Tiptap.RichTextEssentials\", \"Umb.Tiptap.Anchor\", \"Umb.Tiptap.Block\", \"Umb.Tiptap.Blockquote\", \"Umb.Tiptap.Bold\", \"Umb.Tiptap.BulletList\", \"Umb.Tiptap.CodeBlock\", \"Umb.Tiptap.Embed\", \"Umb.Tiptap.Figure\", \"Umb.Tiptap.Heading\", \"Umb.Tiptap.HorizontalRule\", \"Umb.Tiptap.HtmlAttributeClass\", \"Umb.Tiptap.HtmlAttributeDataset\", \"Umb.Tiptap.HtmlAttributeId\", \"Umb.Tiptap.HtmlAttributeStyle\", \"Umb.Tiptap.HtmlTagDiv\", \"Umb.Tiptap.HtmlTagSpan\", \"Umb.Tiptap.Image\", \"Umb.Tiptap.Italic\", \"Umb.Tiptap.Link\", \"Umb.Tiptap.MediaUpload\", \"Umb.Tiptap.OrderedList\", \"Umb.Tiptap.Strike\", \"Umb.Tiptap.Subscript\", \"Umb.Tiptap.Superscript\", \"Umb.Tiptap.Table\", \"Umb.Tiptap.TextAlign\", \"Umb.Tiptap.TextDirection\", \"Umb.Tiptap.TextIndent\", \"Umb.Tiptap.TrailingNode\", \"Umb.Tiptap.Underline\"], \"maxImageSize\": 500, \"overlaySize\": \"medium\", \"toolbar\": [[[\"Umb.Tiptap.Toolbar.SourceEditor\"], [\"Umb.Tiptap.Toolbar.Bold\", \"Umb.Tiptap.Toolbar.Italic\", \"Umb.Tiptap.Toolbar.Underline\"], [\"Umb.Tiptap.Toolbar.TextAlignLeft\", \"Umb.Tiptap.Toolbar.TextAlignCenter\", \"Umb.Tiptap.Toolbar.TextAlignRight\"], [\"Umb.Tiptap.Toolbar.BulletList\", \"Umb.Tiptap.Toolbar.OrderedList\"], [\"Umb.Tiptap.Toolbar.Blockquote\", \"Umb.Tiptap.Toolbar.HorizontalRule\"], [\"Umb.Tiptap.Toolbar.Link\", \"Umb.Tiptap.Toolbar.Unlink\"], [\"Umb.Tiptap.Toolbar.MediaPicker\", \"Umb.Tiptap.Toolbar.EmbeddedMedia\"]]]}", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.RichtextEditor, + EditorAlias = Constants.PropertyEditors.Aliases.RichText, + EditorUiAlias = "Umb.PropertyEditorUi.Tiptap", + DbType = "Ntext", + Configuration = "{\"extensions\": [\"Umb.Tiptap.RichTextEssentials\", \"Umb.Tiptap.Anchor\", \"Umb.Tiptap.Block\", \"Umb.Tiptap.Blockquote\", \"Umb.Tiptap.Bold\", \"Umb.Tiptap.BulletList\", \"Umb.Tiptap.CodeBlock\", \"Umb.Tiptap.Embed\", \"Umb.Tiptap.Figure\", \"Umb.Tiptap.Heading\", \"Umb.Tiptap.HorizontalRule\", \"Umb.Tiptap.HtmlAttributeClass\", \"Umb.Tiptap.HtmlAttributeDataset\", \"Umb.Tiptap.HtmlAttributeId\", \"Umb.Tiptap.HtmlAttributeStyle\", \"Umb.Tiptap.HtmlTagDiv\", \"Umb.Tiptap.HtmlTagSpan\", \"Umb.Tiptap.Image\", \"Umb.Tiptap.Italic\", \"Umb.Tiptap.Link\", \"Umb.Tiptap.MediaUpload\", \"Umb.Tiptap.OrderedList\", \"Umb.Tiptap.Strike\", \"Umb.Tiptap.Subscript\", \"Umb.Tiptap.Superscript\", \"Umb.Tiptap.Table\", \"Umb.Tiptap.TextAlign\", \"Umb.Tiptap.TextDirection\", \"Umb.Tiptap.TextIndent\", \"Umb.Tiptap.TrailingNode\", \"Umb.Tiptap.Underline\"], \"maxImageSize\": 500, \"overlaySize\": \"medium\", \"toolbar\": [[[\"Umb.Tiptap.Toolbar.SourceEditor\"], [\"Umb.Tiptap.Toolbar.Bold\", \"Umb.Tiptap.Toolbar.Italic\", \"Umb.Tiptap.Toolbar.Underline\"], [\"Umb.Tiptap.Toolbar.TextAlignLeft\", \"Umb.Tiptap.Toolbar.TextAlignCenter\", \"Umb.Tiptap.Toolbar.TextAlignRight\"], [\"Umb.Tiptap.Toolbar.BulletList\", \"Umb.Tiptap.Toolbar.OrderedList\"], [\"Umb.Tiptap.Toolbar.Blockquote\", \"Umb.Tiptap.Toolbar.HorizontalRule\"], [\"Umb.Tiptap.Toolbar.Link\", \"Umb.Tiptap.Toolbar.Unlink\"], [\"Umb.Tiptap.Toolbar.MediaPicker\", \"Umb.Tiptap.Toolbar.EmbeddedMedia\"]]]}", + }); } if (_database.Exists(Constants.DataTypes.Textbox)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.Textbox, - EditorAlias = Constants.PropertyEditors.Aliases.TextBox, - EditorUiAlias = "Umb.PropertyEditorUi.TextBox", - DbType = "Nvarchar", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.Textbox, + EditorAlias = Constants.PropertyEditors.Aliases.TextBox, + EditorUiAlias = "Umb.PropertyEditorUi.TextBox", + DbType = "Nvarchar", + }); } if (_database.Exists(Constants.DataTypes.Textarea)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.Textarea, - EditorAlias = Constants.PropertyEditors.Aliases.TextArea, - EditorUiAlias = "Umb.PropertyEditorUi.TextArea", - DbType = "Ntext", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.Textarea, + EditorAlias = Constants.PropertyEditors.Aliases.TextArea, + EditorUiAlias = "Umb.PropertyEditorUi.TextArea", + DbType = "Ntext", + }); } if (_database.Exists(Constants.DataTypes.Upload)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.Upload, - EditorAlias = Constants.PropertyEditors.Aliases.UploadField, - EditorUiAlias = "Umb.PropertyEditorUi.UploadField", - DbType = "Nvarchar", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.Upload, + EditorAlias = Constants.PropertyEditors.Aliases.UploadField, + EditorUiAlias = "Umb.PropertyEditorUi.UploadField", + DbType = "Nvarchar", + }); } InsertDataTypeDto( @@ -2188,42 +1965,49 @@ string GridCollectionView(string collectionViewType) => "Umb.PropertyEditorUi.Label", "Nvarchar", "{\"umbracoDataValueType\":\"STRING\"}"); + InsertDataTypeDto( Constants.DataTypes.LabelInt, Constants.PropertyEditors.Aliases.Label, "Umb.PropertyEditorUi.Label", "Integer", "{\"umbracoDataValueType\":\"INT\"}"); + InsertDataTypeDto( Constants.DataTypes.LabelBigint, Constants.PropertyEditors.Aliases.Label, "Umb.PropertyEditorUi.Label", "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\"}"); + InsertDataTypeDto( Constants.DataTypes.LabelDateTime, Constants.PropertyEditors.Aliases.Label, "Umb.PropertyEditorUi.Label", "Date", "{\"umbracoDataValueType\":\"DATETIME\"}"); + InsertDataTypeDto( Constants.DataTypes.LabelDecimal, Constants.PropertyEditors.Aliases.Label, "Umb.PropertyEditorUi.Label", "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}"); + InsertDataTypeDto( Constants.DataTypes.LabelTime, Constants.PropertyEditors.Aliases.Label, "Umb.PropertyEditorUi.Label", "Date", "{\"umbracoDataValueType\":\"TIME\"}"); + InsertDataTypeDto( Constants.DataTypes.LabelBytes, Constants.PropertyEditors.Aliases.Label, "Umb.PropertyEditorUi.Label", "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\", \"labelTemplate\":\"{=value | bytes}\"}"); + InsertDataTypeDto( Constants.DataTypes.LabelPixels, Constants.PropertyEditors.Aliases.Label, @@ -2233,33 +2017,25 @@ string GridCollectionView(string collectionViewType) => if (_database.Exists(Constants.DataTypes.DateTime)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.DateTime, - EditorAlias = Constants.PropertyEditors.Aliases.DateTime, - EditorUiAlias = "Umb.PropertyEditorUi.DatePicker", - DbType = "Date", - Configuration = "{\"format\":\"YYYY-MM-DD HH:mm:ss\"}", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.DateTime, + EditorAlias = Constants.PropertyEditors.Aliases.DateTime, + EditorUiAlias = "Umb.PropertyEditorUi.DatePicker", + DbType = "Date", + Configuration = "{\"format\":\"YYYY-MM-DD HH:mm:ss\"}", + }); } if (_database.Exists(-37)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = -37, - EditorAlias = Constants.PropertyEditors.Aliases.ColorPicker, - EditorUiAlias = "Umb.PropertyEditorUi.ColorPicker", - DbType = "Nvarchar", - }); + Insert(new DataTypeDto + { + NodeId = -37, + EditorAlias = Constants.PropertyEditors.Aliases.ColorPicker, + EditorUiAlias = "Umb.PropertyEditorUi.ColorPicker", + DbType = "Nvarchar", + }); } InsertDataTypeDto( @@ -2271,33 +2047,25 @@ string GridCollectionView(string collectionViewType) => if (_database.Exists(-40)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = -40, - EditorAlias = Constants.PropertyEditors.Aliases.RadioButtonList, - EditorUiAlias = "Umb.PropertyEditorUi.RadioButtonList", - DbType = "Nvarchar", - }); + Insert(new DataTypeDto + { + NodeId = -40, + EditorAlias = Constants.PropertyEditors.Aliases.RadioButtonList, + EditorUiAlias = "Umb.PropertyEditorUi.RadioButtonList", + DbType = "Nvarchar", + }); } if (_database.Exists(-41)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = -41, - EditorAlias = Constants.PropertyEditors.Aliases.DateTime, - EditorUiAlias = "Umb.PropertyEditorUi.DatePicker", - DbType = "Date", - Configuration = "{\"format\":\"YYYY-MM-DD\"}", - }); + Insert(new DataTypeDto + { + NodeId = -41, + EditorAlias = Constants.PropertyEditors.Aliases.DateTime, + EditorUiAlias = "Umb.PropertyEditorUi.DatePicker", + DbType = "Date", + Configuration = "{\"format\":\"YYYY-MM-DD\"}", + }); } InsertDataTypeDto( @@ -2309,298 +2077,226 @@ string GridCollectionView(string collectionViewType) => if (_database.Exists(-43)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = -43, - EditorAlias = Constants.PropertyEditors.Aliases.CheckBoxList, - EditorUiAlias = "Umb.PropertyEditorUi.CheckBoxList", - DbType = "Ntext", - }); + Insert(new DataTypeDto + { + NodeId = -43, + EditorAlias = Constants.PropertyEditors.Aliases.CheckBoxList, + EditorUiAlias = "Umb.PropertyEditorUi.CheckBoxList", + DbType = "Ntext", + }); } if (_database.Exists(Constants.DataTypes.Tags)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.Tags, - EditorAlias = Constants.PropertyEditors.Aliases.Tags, - EditorUiAlias = "Umb.PropertyEditorUi.Tags", - DbType = "Ntext", - Configuration = "{\"group\":\"default\", \"storageType\":\"Json\"}", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.Tags, + EditorAlias = Constants.PropertyEditors.Aliases.Tags, + EditorUiAlias = "Umb.PropertyEditorUi.Tags", + DbType = "Ntext", + Configuration = "{\"group\":\"default\", \"storageType\":\"Json\"}", + }); } if (_database.Exists(Constants.DataTypes.ImageCropper)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.ImageCropper, - EditorAlias = Constants.PropertyEditors.Aliases.ImageCropper, - EditorUiAlias = "Umb.PropertyEditorUi.ImageCropper", - DbType = "Ntext", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.ImageCropper, + EditorAlias = Constants.PropertyEditors.Aliases.ImageCropper, + EditorUiAlias = "Umb.PropertyEditorUi.ImageCropper", + DbType = "Ntext", + }); } if (_database.Exists(Constants.DataTypes.DefaultContentListView)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.DefaultContentListView, - EditorAlias = Constants.PropertyEditors.Aliases.ListView, - EditorUiAlias = "Umb.PropertyEditorUi.Collection", - DbType = "Nvarchar", - Configuration = + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.DefaultContentListView, + EditorAlias = Constants.PropertyEditors.Aliases.ListView, + EditorUiAlias = "Umb.PropertyEditorUi.Collection", + DbType = "Nvarchar", + Configuration = "{\"pageSize\":100, \"orderBy\":\"updateDate\", \"orderDirection\":\"desc\", \"layouts\":" + Layouts("Document") + ", \"includeProperties\":[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":true},{\"alias\":\"creator\",\"header\":\"Updated by\",\"isSystem\":true}]}", - }); + }); } if (_database.Exists(Constants.DataTypes.DefaultMediaListView)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.DefaultMediaListView, - EditorAlias = Constants.PropertyEditors.Aliases.ListView, - EditorUiAlias = "Umb.PropertyEditorUi.Collection", - DbType = "Nvarchar", - Configuration = + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.DefaultMediaListView, + EditorAlias = Constants.PropertyEditors.Aliases.ListView, + EditorUiAlias = "Umb.PropertyEditorUi.Collection", + DbType = "Nvarchar", + Configuration = "{\"pageSize\":100, \"orderBy\":\"updateDate\", \"orderDirection\":\"desc\", \"layouts\":" + Layouts("Media") + ", \"includeProperties\":[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":true},{\"alias\":\"creator\",\"header\":\"Updated by\",\"isSystem\":true}]}", - }); + }); } if (_database.Exists(Constants.DataTypes.DefaultMembersListView)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.DefaultMembersListView, - EditorAlias = Constants.PropertyEditors.Aliases.ListView, - EditorUiAlias = "Umb.PropertyEditorUi.Collection", - DbType = "Nvarchar", - Configuration = + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.DefaultMembersListView, + EditorAlias = Constants.PropertyEditors.Aliases.ListView, + EditorUiAlias = "Umb.PropertyEditorUi.Collection", + DbType = "Nvarchar", + Configuration = "{\"pageSize\":10, \"orderBy\":\"username\", \"orderDirection\":\"asc\", \"includeProperties\":[{\"alias\":\"username\",\"isSystem\":true},{\"alias\":\"email\",\"isSystem\":true},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":true}]}", - }); + }); } // New UDI pickers with newer Ids if (_database.Exists(1046)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1046, - EditorAlias = Constants.PropertyEditors.Aliases.ContentPicker, - EditorUiAlias = "Umb.PropertyEditorUi.DocumentPicker", - DbType = "Nvarchar", - }); + Insert(new DataTypeDto + { + NodeId = 1046, + EditorAlias = Constants.PropertyEditors.Aliases.ContentPicker, + EditorUiAlias = "Umb.PropertyEditorUi.DocumentPicker", + DbType = "Nvarchar", + }); } if (_database.Exists(1047)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1047, - EditorAlias = Constants.PropertyEditors.Aliases.MemberPicker, - EditorUiAlias = "Umb.PropertyEditorUi.MemberPicker", - DbType = "Nvarchar", - }); + Insert(new DataTypeDto + { + NodeId = 1047, + EditorAlias = Constants.PropertyEditors.Aliases.MemberPicker, + EditorUiAlias = "Umb.PropertyEditorUi.MemberPicker", + DbType = "Nvarchar", + }); } if (_database.Exists(1050)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1050, - EditorAlias = Constants.PropertyEditors.Aliases.MultiUrlPicker, - EditorUiAlias = "Umb.PropertyEditorUi.MultiUrlPicker", - DbType = "Ntext", - }); + Insert(new DataTypeDto + { + NodeId = 1050, + EditorAlias = Constants.PropertyEditors.Aliases.MultiUrlPicker, + EditorUiAlias = "Umb.PropertyEditorUi.MultiUrlPicker", + DbType = "Ntext", + }); } if (_database.Exists(Constants.DataTypes.UploadVideo)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.UploadVideo, - EditorAlias = Constants.PropertyEditors.Aliases.UploadField, - EditorUiAlias = "Umb.PropertyEditorUi.UploadField", - DbType = "Nvarchar", - Configuration = + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.UploadVideo, + EditorAlias = Constants.PropertyEditors.Aliases.UploadField, + EditorUiAlias = "Umb.PropertyEditorUi.UploadField", + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[\"mp4\",\"webm\",\"ogv\"]}", - }); + }); } if (_database.Exists(Constants.DataTypes.UploadAudio)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.UploadAudio, - EditorAlias = Constants.PropertyEditors.Aliases.UploadField, - EditorUiAlias = "Umb.PropertyEditorUi.UploadField", - DbType = "Nvarchar", - Configuration = + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.UploadAudio, + EditorAlias = Constants.PropertyEditors.Aliases.UploadField, + EditorUiAlias = "Umb.PropertyEditorUi.UploadField", + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[\"mp3\",\"weba\",\"oga\",\"opus\"]}", - }); + }); } if (_database.Exists(Constants.DataTypes.UploadArticle)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.UploadArticle, - EditorAlias = Constants.PropertyEditors.Aliases.UploadField, - EditorUiAlias = "Umb.PropertyEditorUi.UploadField", - DbType = "Nvarchar", - Configuration = + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.UploadArticle, + EditorAlias = Constants.PropertyEditors.Aliases.UploadField, + EditorUiAlias = "Umb.PropertyEditorUi.UploadField", + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[\"pdf\",\"docx\",\"doc\"]}", - }); + }); } if (_database.Exists(Constants.DataTypes.UploadVectorGraphics)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = Constants.DataTypes.UploadVectorGraphics, - EditorAlias = Constants.PropertyEditors.Aliases.UploadField, - EditorUiAlias = "Umb.PropertyEditorUi.UploadField", - DbType = "Nvarchar", - Configuration = "{\"fileExtensions\":[\"svg\"]}", - }); + Insert(new DataTypeDto + { + NodeId = Constants.DataTypes.UploadVectorGraphics, + EditorAlias = Constants.PropertyEditors.Aliases.UploadField, + EditorUiAlias = "Umb.PropertyEditorUi.UploadField", + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[\"svg\"]}", + }); } if (_database.Exists(1051)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1051, - EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, - EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", - DbType = "Ntext", - Configuration = "{\"multiple\": false, \"validationLimit\":{\"min\":0,\"max\":1}}", - }); + Insert(new DataTypeDto + { + NodeId = 1051, + EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, + EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", + DbType = "Ntext", + Configuration = "{\"multiple\": false, \"validationLimit\":{\"min\":0,\"max\":1}}", + }); } if (_database.Exists(1052)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1052, - EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, - EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", - DbType = "Ntext", - Configuration = "{\"multiple\": true}", - }); + Insert(new DataTypeDto + { + NodeId = 1052, + EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, + EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", + DbType = "Ntext", + Configuration = "{\"multiple\": true}", + }); } if (_database.Exists(1053)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1053, - EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, - EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", - DbType = "Ntext", - Configuration = "{\"filter\":\"" + Constants.MediaTypes.Guids.Image + + Insert(new DataTypeDto + { + NodeId = 1053, + EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, + EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", + DbType = "Ntext", + Configuration = "{\"filter\":\"" + Constants.MediaTypes.Guids.Image + "\", \"multiple\": false, \"validationLimit\":{\"min\":0,\"max\":1}}", - }); + }); } if (_database.Exists(1054)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1054, - EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, - EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", - DbType = "Ntext", - Configuration = "{\"filter\":\"" + Constants.MediaTypes.Guids.Image + + Insert(new DataTypeDto + { + NodeId = 1054, + EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker3, + EditorUiAlias = "Umb.PropertyEditorUi.MediaPicker", + DbType = "Ntext", + Configuration = "{\"filter\":\"" + Constants.MediaTypes.Guids.Image + "\", \"multiple\": true}", - }); + }); } if (_database.Exists(1055)) { - _database.Insert( - Constants.DatabaseSchema.Tables.DataType, - "pk", - false, - new DataTypeDto - { - NodeId = 1055, - EditorAlias = Constants.PropertyEditors.Aliases.DateTimeWithTimeZone, - EditorUiAlias = "Umb.PropertyEditorUi.DateTimeWithTimeZonePicker", - DbType = "Ntext", - Configuration = "{\"timeFormat\": \"HH:mm\", \"timeZones\": {\"mode\": \"all\"}}", - }); + Insert(new DataTypeDto + { + NodeId = 1055, + EditorAlias = Constants.PropertyEditors.Aliases.DateTimeWithTimeZone, + EditorUiAlias = "Umb.PropertyEditorUi.DateTimeWithTimeZonePicker", + DbType = "Ntext", + Configuration = "{\"timeFormat\": \"HH:mm\", \"timeZones\": {\"mode\": \"all\"}}", + }); } } @@ -2614,6 +2310,7 @@ private void CreateRelationTypeData() Constants.ObjectTypes.Document, true, false); + CreateRelationTypeData( 2, Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, @@ -2622,6 +2319,7 @@ private void CreateRelationTypeData() Constants.ObjectTypes.Document, false, false); + CreateRelationTypeData( 3, Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, @@ -2630,6 +2328,7 @@ private void CreateRelationTypeData() Constants.ObjectTypes.Media, false, false); + CreateRelationTypeData( 4, Constants.Conventions.RelationTypes.RelatedMediaAlias, @@ -2638,6 +2337,7 @@ private void CreateRelationTypeData() null, false, true); + CreateRelationTypeData( 5, Constants.Conventions.RelationTypes.RelatedDocumentAlias, @@ -2646,6 +2346,7 @@ private void CreateRelationTypeData() null, false, true); + CreateRelationTypeData( 6, Constants.Conventions.RelationTypes.RelatedMemberAlias, @@ -2666,19 +2367,18 @@ private void CreateRelationTypeData( bool dual, bool isDependency) { - var relationType = new RelationTypeDto - { - Id = id, - Alias = alias, - ChildObjectType = childObjectType, - ParentObjectType = parentObjectType, - Dual = dual, - Name = name, - IsDependency = isDependency, - }; - relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name); - - _database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType); + Insert( + new RelationTypeDto + { + Id = id, + Alias = alias, + ChildObjectType = childObjectType, + ParentObjectType = parentObjectType, + Dual = dual, + Name = name, + IsDependency = isDependency, + UniqueId = CreateUniqueRelationTypeId(alias, name) + }); } private void CreateKeyValueData() @@ -2688,22 +2388,13 @@ private void CreateKeyValueData() var stateValueKey = upgrader.StateValueKey; var finalState = upgrader.Plan.FinalState; - _database.Insert( - Constants.DatabaseSchema.Tables.KeyValue, - "key", - false, - new KeyValueDto { Key = stateValueKey, Value = finalState, UpdateDate = DateTime.UtcNow }); - + Insert(new KeyValueDto { Key = stateValueKey, Value = finalState, UpdateDate = DateTime.UtcNow }); upgrader = new Upgrader(new UmbracoPremigrationPlan()); stateValueKey = upgrader.StateValueKey; finalState = upgrader.Plan.FinalState; - _database.Insert( - Constants.DatabaseSchema.Tables.KeyValue, - "key", - false, - new KeyValueDto { Key = stateValueKey, Value = finalState, UpdateDate = DateTime.UtcNow }); + Insert(new KeyValueDto { Key = stateValueKey, Value = finalState, UpdateDate = DateTime.UtcNow }); } private void CreateLogViewerQueryData() @@ -2712,20 +2403,17 @@ private void CreateLogViewerQueryData() { LogViewerQueryDto dto = _defaultLogQueries[i]; dto.Id = i + 1; - _database.Insert(Constants.DatabaseSchema.Tables.LogViewerQuery, "id", false, dto); + Insert(dto); } } - private void ConditionalInsert( - string configKey, - string id, - TDto dto, - string tableName, - string primaryKeyName, - bool autoIncrement = false) + private void ConditionalInsert(string configKey, string id, TDto dto) { - var alwaysInsert = _entitiesToAlwaysCreate.ContainsKey(configKey) && - _entitiesToAlwaysCreate[configKey].InvariantContains(id); + var alwaysInsert = false; + if (_entitiesToAlwaysCreate.TryGetValue(configKey, out IList? alwaysCreateIds)) + { + alwaysInsert = alwaysCreateIds.InvariantContains(id); + } InstallDefaultDataSettings installDefaultDataSettings = _installDefaultDataSettings.Get(configKey); @@ -2752,6 +2440,28 @@ private void ConditionalInsert( return; } - _database.Insert(tableName, primaryKeyName, autoIncrement, dto); + Insert(dto); } + + private void Insert(T poco) + { + ArgumentNullException.ThrowIfNull(poco); + ArgumentNullException.ThrowIfNull(_pocoDataFactory); + + PocoData pocoData = _pocoDataFactory.ForType(poco.GetType()); + var autoIncrement = UseAutoIncrement(); + + _database.Insert( + pocoData.TableInfo.TableName, + null, + autoIncrement, + poco); + } + + private bool UseAutoIncrement() + { + return ((IUmbracoDatabase)_database).SqlContext.DatabaseType is PostgreSQLDatabaseType; + } + +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } diff --git a/src/Umbraco.Infrastructure/Migrations/Notifications/DatabaseSchemaInitializedNotification.cs b/src/Umbraco.Infrastructure/Migrations/Notifications/DatabaseSchemaInitializedNotification.cs new file mode 100644 index 000000000000..15165c73fa0e --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/Notifications/DatabaseSchemaInitializedNotification.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NPoco; +using Umbraco.Cms.Core.Events; +using Umbraco.Cms.Core.Notifications; +using Umbraco.Cms.Infrastructure.Persistence; + +namespace Umbraco.Cms.Infrastructure.Migrations.Notifications +{ + public sealed class DatabaseSchemaInitializedNotification : StatefulNotification + { + public DatabaseSchemaInitializedNotification(IUmbracoDatabase database) + { + Database = database; + } + + public IUmbracoDatabase Database { get; } + } +} diff --git a/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs index 383b091dfb89..003d71aa864f 100644 --- a/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs +++ b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs @@ -43,6 +43,14 @@ public static Sql WhereClosure(this Sql sql, Exp return sql.Where(predicate, alias).Append(")"); } + // moved to NPocoSqlWhereExtensions.cs + // can be removed after code review of PR #21577 or when in main branch + //public static Sql WhereParam(this Sql sql, Expression> field, string param) + //{ + // string s = $"{sql.GetColumns(columnExpressions: [field], withAlias: false).FirstOrDefault()} = {param}"; + // return sql.Where(s, []); + //} + /// /// Appends a WHERE clause to the Sql statement. /// @@ -87,7 +95,25 @@ public static Sql Where(this Sql /// The Sql statement. public static Sql WhereIn(this Sql sql, Expression> field, IEnumerable? values) { + if (values == null) + { + return sql; + } + var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(field); + + string[] stringValues = [.. values.OfType()]; // This is necessary to avoid failing attempting to convert to string[] when values contains non-string types + if (stringValues.Length > 0) + { + Attempt attempt = values.TryConvertTo(); + if (attempt.Success) + { + values = attempt.Result?.Select(v => v?.ToLower()); + sql.Where($"LOWER({fieldName}) IN (@values)", new { values }); + return sql; + } + } + sql.Where($"{fieldName} IN (@values)", new { values }); return sql; } @@ -788,6 +814,28 @@ public static Sql SelectMax(this Sql sql, Expres return sql.Select($"COALESCE(MAX ({sql.SqlContext.SqlSyntax.GetFieldName(field)}), {coalesceValue})"); } + /// + /// Adds a SQL SELECT statement to retrieve the maximum value of the specified field from the table associated + /// with the specified DTO type. + /// + /// The type of the Data Transfer Object (DTO) that represents the table from which the maximum value will be + /// selected. + /// The SQL query builder to which the SELECT statement will be appended. Cannot be . + /// An expression specifying the field for which the maximum value will be calculated. Cannot be . + /// COALESCE string value. + /// A modified SQL query builder that includes the SELECT statement for the maximum value of the specified + /// field or the coalesceValue. + // moved to NPocoSqlSelectExtensions.cs + // can be removed after code review of PR #21577 or when in main branch + //public static Sql SelectMax(this Sql sql, Expression> field, string coalesceValue) + //{ + // ArgumentNullException.ThrowIfNull(sql); + // ArgumentNullException.ThrowIfNull(field); + + // return sql.Select($"COALESCE(MAX {sql.SqlContext.SqlSyntax.GetFieldName(field)}), '{coalesceValue}')"); + //} + /// /// Adds a SQL SELECT statement to retrieve the sum of the values of the specified field from the table associated /// with the specified DTO type. @@ -1483,20 +1531,22 @@ public static Sql AppendForUpdateHint(this Sql sql) #region Aliasing - internal static string GetAliasedField(this Sql sql, string field) - { - // get alias, if aliased - // - // regex looks for pattern "([\w+].[\w+]) AS ([\w+])" ie "(field) AS (alias)" - // and, if found & a group's field matches the field name, returns the alias - // - // so... if query contains "[umbracoNode].[nodeId] AS [umbracoNode__nodeId]" - // then GetAliased for "[umbracoNode].[nodeId]" returns "[umbracoNode__nodeId]" - - MatchCollection matches = sql.SqlContext.SqlSyntax.AliasRegex.Matches(sql.SQL); - Match? match = matches.Cast().FirstOrDefault(m => m.Groups[1].Value.InvariantEquals(field)); - return match == null ? field : match.Groups[2].Value; - } + // moved to NPocoSqlExtensionsInternal.cs + // can be removed after code review of PR #21577 or when in main branch + //internal static string GetAliasedField(this Sql sql, string field) + //{ + // // get alias, if aliased + // // + // // regex looks for pattern "([\w+].[\w+]) AS ([\w+])" ie "(field) AS (alias)" + // // and, if found & a group's field matches the field name, returns the alias + // // + // // so... if query contains "[umbracoNode].[nodeId] AS [umbracoNode__nodeId]" + // // then GetAliased for "[umbracoNode].[nodeId]" returns "[umbracoNode__nodeId]" + + // MatchCollection matches = sql.SqlContext.SqlSyntax.AliasRegex.Matches(sql.SQL); + // Match? match = matches.Cast().FirstOrDefault(m => m.Groups[1].Value.InvariantEquals(field)); + // return match == null ? field : match.Groups[2].Value; + //} #endregion @@ -1505,55 +1555,64 @@ internal static string GetAliasedField(this Sql sql, string field) public static Sql AppendSubQuery(this Sql sql, Sql subQuery, string alias) { // Append the subquery as a derived table with an alias - sql.Append("(").Append(subQuery.SQL, subQuery.Arguments).Append($") AS {alias}"); + sql.Append("(").Append(subQuery.SQL, subQuery.Arguments).Append($") AS {sql.SqlContext.SqlSyntax.GetQuotedName(alias)}"); return sql; } - private static string[] GetColumns(this Sql sql, string? tableAlias = null, string? referenceName = null, Expression>[]? columnExpressions = null, bool withAlias = true, bool forInsert = false) - { - PocoData? pd = sql.SqlContext.PocoDataFactory.ForType(typeof(TDto)); - var tableName = tableAlias ?? pd.TableInfo.TableName; - var queryColumns = pd.QueryColumns.ToList(); - - Dictionary? aliases = null; - - if (columnExpressions != null && columnExpressions.Length > 0) - { - var names = columnExpressions.Select(x => - { - (MemberInfo member, var alias) = ExpressionHelper.FindProperty(x); - var field = member as PropertyInfo; - var fieldName = field?.GetColumnName(); - if (alias != null && fieldName is not null) - { - aliases ??= new Dictionary(); - aliases[fieldName] = alias; - } - return fieldName; - }).ToArray(); - - //only get the columns that exist in the selected names - queryColumns = queryColumns.Where(x => names.Contains(x.Key)).ToList(); - - //ensure the order of the columns in the expressions is the order in the result - queryColumns.Sort((a, b) => names.IndexOf(a.Key).CompareTo(names.IndexOf(b.Key))); - } - - string? GetAlias(PocoColumn column) - { - if (aliases != null && aliases.TryGetValue(column.ColumnName, out var alias)) - { - return alias; - } - - return withAlias ? (string.IsNullOrEmpty(column.ColumnAlias) ? column.MemberInfoKey : column.ColumnAlias) : null; - } - - return queryColumns - .Select(x => sql.SqlContext.SqlSyntax.GetColumn(sql.SqlContext.DatabaseType, tableName, x.Value.ColumnName, GetAlias(x.Value)!, referenceName, forInsert: forInsert)) - .ToArray(); - } + // moved to NPocoSqlExtensionsInternal.cs + // can be removed after code review of PR #21577 or when in main branch + //private static string[] GetColumns(this Sql sql, string? tableAlias = null, string? referenceName = null, Expression>[]? columnExpressions = null, bool withAlias = true, bool forInsert = false) + //{ + // PocoData? pd = sql.SqlContext.PocoDataFactory.ForType(typeof(TDto)); + // var tableName = tableAlias ?? pd.TableInfo.TableName; + // var queryColumns = pd.QueryColumns.ToList(); + + // Dictionary? aliases = null; + + // if (columnExpressions != null && columnExpressions.Length > 0) + // { + // var names = columnExpressions.Select(x => + // { + // (MemberInfo member, var alias) = ExpressionHelper.FindProperty(x); + // var field = member as PropertyInfo; + // var fieldName = field?.GetColumnName(); + // if (alias != null && fieldName is not null) + // { + // aliases ??= new Dictionary(); + // aliases[fieldName] = alias; + // } + // return fieldName; + // }).ToArray(); + + // //only get the columns that exist in the selected names + // queryColumns = queryColumns.Where(x => names.Contains(x.Key)).ToList(); + + // //ensure the order of the columns in the expressions is the order in the result + // queryColumns.Sort((a, b) => names.IndexOf(a.Key).CompareTo(names.IndexOf(b.Key))); + // } + + // string? GetAlias(PocoColumn column) + // { + // if (aliases != null && aliases.TryGetValue(column.ColumnName, out var alias)) + // { + // return alias; + // } + + // if ((column.MemberInfoKey.InvariantEquals("uniqueid") && !column.MemberInfoKey.Equals("uniqueId")) + // || (column.MemberInfoKey.InvariantEquals("languageid") && !column.MemberInfoKey.Equals("languageId"))) + // { + // return withAlias ? (string.IsNullOrEmpty(column.ColumnAlias) ? column.ColumnName + // : column.ColumnAlias) : null; + // } + + // return withAlias ? (string.IsNullOrEmpty(column.ColumnAlias) ? column.MemberInfoKey : column.ColumnAlias) : null; + // } + + // return queryColumns + // .Select(x => sql.SqlContext.SqlSyntax.GetColumn(sql.SqlContext.DatabaseType, tableName, x.Value.ColumnName, GetAlias(x.Value)!, referenceName, forInsert: forInsert)) + // .ToArray(); + //} public static string GetTableName(this Type type) { @@ -1564,11 +1623,13 @@ public static string GetTableName(this Type type) return string.IsNullOrWhiteSpace(attr?.Value) ? string.Empty : attr.Value; } - private static string GetColumnName(this PropertyInfo column) - { - ColumnAttribute? attr = column.FirstAttribute(); - return string.IsNullOrWhiteSpace(attr?.Name) ? column.Name : attr.Name; - } + // moved to SqlSyntaxExtensions.cs + // can be removed after code review of PR #21577 or when in main branch + //private static string GetColumnName(this PropertyInfo column) + //{ + // ColumnAttribute? attr = column.FirstAttribute(); + // return string.IsNullOrWhiteSpace(attr?.Name) ? column.Name : attr.Name; + //} public static string ToText(this Sql sql) { diff --git a/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensionsInternal.cs b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensionsInternal.cs new file mode 100644 index 000000000000..2d7d84344aa6 --- /dev/null +++ b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensionsInternal.cs @@ -0,0 +1,78 @@ +using System.Linq.Expressions; +using System.Reflection; +using System.Text.RegularExpressions; +using NPoco; +using Umbraco.Cms.Core; +using Umbraco.Cms.Infrastructure.Persistence; + +namespace Umbraco.Extensions +{ + public static partial class NPocoSqlExtensions + { + internal static string GetAliasedField(this Sql sql, string field) + { + // get alias, if aliased + // + // regex looks for pattern "([\w+].[\w+]) AS ([\w+])" ie "(field) AS (alias)" + // and, if found & a group's field matches the field name, returns the alias + // + // so... if query contains "[umbracoNode].[nodeId] AS [umbracoNode__nodeId]" + // then GetAliased for "[umbracoNode].[nodeId]" returns "[umbracoNode__nodeId]" + + MatchCollection matches = sql.SqlContext.SqlSyntax.AliasRegex.Matches(sql.SQL); + Match? match = matches.Cast().FirstOrDefault(m => m.Groups[1].Value.InvariantEquals(field)); + return match == null ? field : match.Groups[2].Value; + } + + internal static string[] GetColumns(this Sql sql, string? tableAlias = null, string? referenceName = null, Expression>[]? columnExpressions = null, bool withAlias = true, bool forInsert = false) + { + PocoData? pd = sql.SqlContext.PocoDataFactory.ForType(typeof(TDto)); + var tableName = tableAlias ?? pd.TableInfo.TableName; + var queryColumns = pd.QueryColumns.ToList(); + + Dictionary? aliases = null; + + if (columnExpressions != null && columnExpressions.Length > 0) + { + var names = columnExpressions.Select(x => + { + (MemberInfo member, var alias) = ExpressionHelper.FindProperty(x); + var field = member as PropertyInfo; + var fieldName = field?.GetColumnName(); + if (alias != null && fieldName is not null) + { + aliases ??= new Dictionary(); + aliases[fieldName] = alias; + } + return fieldName; + }).ToArray(); + + //only get the columns that exist in the selected names + queryColumns = queryColumns.Where(x => names.Contains(x.Key)).ToList(); + + //ensure the order of the columns in the expressions is the order in the result + queryColumns.Sort((a, b) => names.IndexOf(a.Key).CompareTo(names.IndexOf(b.Key))); + } + + string? GetAlias(PocoColumn column) + { + if (aliases != null && aliases.TryGetValue(column.ColumnName, out var alias)) + { + return alias; + } + + return withAlias ? (string.IsNullOrEmpty(column.ColumnAlias) ? column.MemberInfoKey : column.ColumnAlias) : null; + } + + return queryColumns + .Select(x => sql.SqlContext.SqlSyntax.GetColumn( + sql.SqlContext.DatabaseType, + tableName, + x.Value.ColumnName, + GetAlias(x.Value), + referenceName, + forInsert: forInsert)) + .ToArray(); + } + } +} diff --git a/src/Umbraco.Infrastructure/Persistence/NPocoSqlSelectExtensions.cs b/src/Umbraco.Infrastructure/Persistence/NPocoSqlSelectExtensions.cs new file mode 100644 index 000000000000..91f4c2a5d75e --- /dev/null +++ b/src/Umbraco.Infrastructure/Persistence/NPocoSqlSelectExtensions.cs @@ -0,0 +1,37 @@ +using System.Collections; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using NPoco; +using Umbraco.Cms.Core; +using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Infrastructure.Persistence.Querying; +using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax; + +namespace Umbraco.Extensions +{ + public static partial class NPocoSqlExtensions + { + /// + /// Adds a SQL SELECT statement to retrieve the maximum value of the specified field from the table associated + /// with the specified DTO type. + /// + /// The type of the Data Transfer Object (DTO) that represents the table from which the maximum value will be + /// selected. + /// The SQL query builder to which the SELECT statement will be appended. Cannot be . + /// An expression specifying the field for which the maximum value will be calculated. Cannot be . + /// COALESCE string value. + /// A modified SQL query builder that includes the SELECT statement for the maximum value of the specified + /// field or the coalesceValue. + public static Sql SelectMax(this Sql sql, Expression> field, string coalesceValue) + { + ArgumentNullException.ThrowIfNull(sql); + ArgumentNullException.ThrowIfNull(field); + + return sql.Select($"COALESCE(MAX {sql.SqlContext.SqlSyntax.GetFieldName(field)}), '{coalesceValue}')"); + } + + } +} diff --git a/src/Umbraco.Infrastructure/Persistence/NPocoSqlWhereExtensions.cs b/src/Umbraco.Infrastructure/Persistence/NPocoSqlWhereExtensions.cs new file mode 100644 index 000000000000..3dd6a2f5b7c8 --- /dev/null +++ b/src/Umbraco.Infrastructure/Persistence/NPocoSqlWhereExtensions.cs @@ -0,0 +1,22 @@ +using System.Collections; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using NPoco; +using Umbraco.Cms.Core; +using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Infrastructure.Persistence.Querying; +using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax; + +namespace Umbraco.Extensions +{ + public static partial class NPocoSqlExtensions + { + public static Sql WhereParam(this Sql sql, Expression> field, string param) + { + string s = $"{sql.GetColumns(columnExpressions: [field], withAlias: false).FirstOrDefault()} = {param}"; + return sql.Where(s, []); + } + } +} diff --git a/src/Umbraco.Infrastructure/Persistence/Querying/Query.cs b/src/Umbraco.Infrastructure/Persistence/Querying/Query.cs index c66e121cf736..bb856bae0fba 100644 --- a/src/Umbraco.Infrastructure/Persistence/Querying/Query.cs +++ b/src/Umbraco.Infrastructure/Persistence/Querying/Query.cs @@ -2,7 +2,9 @@ using System.Linq.Expressions; using System.Text; using NPoco; +using Umbraco.Cms.Core; using Umbraco.Cms.Core.Persistence.Querying; +using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.Persistence.Querying; @@ -45,10 +47,24 @@ public virtual IQuery WhereIn(Expression>? fieldSelector, IEn var expressionHelper = new ModelToSqlExpressionVisitor(_sqlContext.SqlSyntax, _sqlContext.Mappers); var whereExpression = expressionHelper.Visit(fieldSelector); + + FixCompareCasing(ref values, ref whereExpression); + _wheres.Add(new Tuple(whereExpression + " IN (@values)", new object[] { new { values } })); return this; } + private static void FixCompareCasing(ref IEnumerable? values, ref string whereExpression) + { + Attempt attempt = values.TryConvertTo(); + if (attempt.Success) + { + // fix for case insensitive comparison in databases like PostgreSQL + whereExpression = $"LOWER({whereExpression})"; + values = attempt.Result?.Select(v => v.ToLower()); + } + } + /// /// Adds a where-not-in clause to the query. /// @@ -61,6 +77,9 @@ public virtual IQuery WhereNotIn(Expression>? fieldSelector, var expressionHelper = new ModelToSqlExpressionVisitor(_sqlContext.SqlSyntax, _sqlContext.Mappers); var whereExpression = expressionHelper.Visit(fieldSelector); + + FixCompareCasing(ref values, ref whereExpression); + _wheres.Add(new Tuple(whereExpression + " NOT IN (@values)", new object[] { new { values } })); return this; } @@ -88,7 +107,7 @@ public virtual IQuery WhereAny(IEnumerable>>? predic { sb = new StringBuilder("("); parameters = new List(); - sql = Sql.BuilderFor(_sqlContext); + sql = NPoco.Sql.BuilderFor(_sqlContext); } else { diff --git a/src/Umbraco.Infrastructure/Persistence/Relations/ContentRelationsUpdate.cs b/src/Umbraco.Infrastructure/Persistence/Relations/ContentRelationsUpdate.cs index 871f530a1e4d..ef99f5b32787 100644 --- a/src/Umbraco.Infrastructure/Persistence/Relations/ContentRelationsUpdate.cs +++ b/src/Umbraco.Infrastructure/Persistence/Relations/ContentRelationsUpdate.cs @@ -162,7 +162,8 @@ private void PersistRelations(IScope scope, IContentBase entity) private sealed class NodeIdKey { - [Column("id")] + public const string PrimaryKeyName = Constants.DatabaseSchema.Columns.PrimaryKeyNameId; + [Column(PrimaryKeyName)] public int NodeId { get; set; } [Column("uniqueId")] diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditRepository.cs index 9b1d6a9f396b..b92cd3bec4a9 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditRepository.cs @@ -32,7 +32,7 @@ public AuditRepository( public IEnumerable Get(AuditType type, IQuery query) { Sql? sqlClause = GetBaseQuery(false) - .Where("(logHeader=@0)", type.ToString()); + .Where($"({SqlSyntax.GetQuotedColumnName("logHeader")}=@0)", type.ToString()); var translator = new SqlTranslator(sqlClause, query); Sql sql = translator.Translate(); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs index f98dac5e9313..c0ccb03f3869 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -545,10 +545,10 @@ private string ApplyCustomOrdering(ref Sql sql, Ordering ordering) { // sorting by a custom field, so set-up sub-query for ORDER BY clause to pull through value // from 'current' content version for the given order by field - var sortedInt = string.Format(SqlContext.SqlSyntax.ConvertIntegerToOrderableString, "intValue"); - var sortedDecimal = string.Format(SqlContext.SqlSyntax.ConvertDecimalToOrderableString, "decimalValue"); - var sortedDate = string.Format(SqlContext.SqlSyntax.ConvertDateToOrderableString, "dateValue"); - var sortedString = "COALESCE(varcharValue,'')"; // assuming COALESCE is ok for all syntaxes + var sortedInt = string.Format(SqlContext.SqlSyntax.ConvertIntegerToOrderableString, QuoteColumnName("intValue")); + var sortedDecimal = string.Format(SqlContext.SqlSyntax.ConvertDecimalToOrderableString, QuoteColumnName("decimalValue")); + var sortedDate = string.Format(SqlContext.SqlSyntax.ConvertDateToOrderableString, QuoteColumnName("dateValue")); + var sortedString = $"COALESCE({QuoteColumnName("varcharValue")},'')"; // assuming COALESCE is ok for all syntaxes // needs to be an outer join since there's no guarantee that any of the nodes have values for this property Sql innerSql = Sql().Select($@"CASE diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs index dc5e0c02f97d..9dc259c6556d 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs @@ -205,10 +205,10 @@ protected override Sql GetBaseQuery(bool isCount) protected override IEnumerable GetDeleteClauses() { var l = (List)base.GetDeleteClauses(); // we know it's a list - l.Add($"DELETE FROM {QuoteTableName(ContentVersionCleanupPolicyDto.TableName)} WHERE {QuoteColumnName("contentTypeId")} = @id"); - l.Add($"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.DocumentType)} WHERE {QuoteColumnName("contentTypeNodeId")} = @id"); - l.Add($"DELETE FROM {QuoteTableName(ContentTypeDto.TableName)} WHERE {QuoteColumnName("nodeId")} = @id"); - l.Add($"DELETE FROM {QuoteTableName(NodeDto.TableName)} WHERE id = @id"); + l.Add($"DELETE FROM {QuoteTableName(ContentVersionCleanupPolicyDto.TableName)} WHERE {QuoteColumnName(ContentVersionCleanupPolicyDto.PrimaryKeyName)} = @id"); + l.Add($"DELETE FROM {QuoteTableName(ContentTypeTemplateDto.TableName)} WHERE {QuoteColumnName(ContentTypeTemplateDto.PrimaryKeyName)} = @id"); + l.Add($"DELETE FROM {QuoteTableName(ContentTypeDto.TableName)} WHERE {QuoteColumnName(ContentTypeDto.NodeIdColumnName)} = @id"); + l.Add($"DELETE FROM {QuoteTableName(NodeDto.TableName)} WHERE {QuoteColumnName(NodeDto.PrimaryKeyColumnName)} = @id"); return l; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index b2b40c2f8435..f949d9548dc8 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1078,10 +1078,10 @@ private void CopyTagData( // select tags to insert: tags pointed to by a relation ship, for proper property/content types, // and of source language, and where we cannot left join to an existing tag with same text, // group and languageId - var targetLanguageIdS = targetLanguageId.HasValue ? targetLanguageId.ToString() : "NULL"; + var targetLanguageIdS = targetLanguageId.HasValue ? targetLanguageId.ToString() : "NULL" + SqlSyntax.GetNullCastSuffix(); Sql sqlSelectTagsToInsert1 = Sql() .SelectDistinct(x => x.Text, x => x.Group) - .Append(", " + targetLanguageIdS) + .Append($", {targetLanguageIdS} ") .From(); sqlSelectTagsToInsert1 @@ -1234,7 +1234,7 @@ private void CopyPropertyData( Database.Execute(sqlDelete); // now insert all property data into the target language that exists under the source language - var targetLanguageIdS = targetLanguageId.HasValue ? targetLanguageId.ToString() : "NULL"; + var targetLanguageIdS = targetLanguageId.HasValue ? targetLanguageId.ToString() : "NULL" + SqlSyntax.GetNullCastSuffix(); var cols = Sql().ColumnsForInsert( x => x.VersionId, x => x.PropertyTypeId, @@ -1658,7 +1658,7 @@ public bool HasContainerInPath(params int[] ids) public bool HasContentNodes(int id) { var sql = new Sql( - $"SELECT CASE WHEN EXISTS (SELECT * FROM {QuoteTableName(ContentDto.TableName)} WHERE {QuoteColumnName("contentTypeId")} = @id) THEN 1 ELSE 0 END", + $"SELECT CASE WHEN EXISTS (SELECT * FROM {QuoteTableName(ContentDto.TableName)} WHERE {QuoteColumnName(ContentDto.ContentTypeIdColumnName)} = @id) THEN 1 ELSE 0 END", new { id }); return Database.ExecuteScalar(sql) == 1; } @@ -1670,18 +1670,18 @@ protected override IEnumerable GetDeleteClauses() // is included here just to be 100% sure since it has a FK on cmsPropertyType. var list = new List { - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.User2NodeNotify)} WHERE {QuoteColumnName("nodeId")} = @id", - $@"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.UserGroup2GranularPermission)} WHERE {QuoteColumnName("uniqueId")} IN - (SELECT {QuoteColumnName("uniqueId")} FROM {QuoteTableName(NodeDto.TableName)} WHERE id = @id)", - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.TagRelationship)} WHERE {QuoteColumnName("nodeId")} = @id", - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.ContentChildType)} WHERE {QuoteColumnName("Id")} = @id", - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.ContentChildType)} WHERE {QuoteColumnName("AllowedId")} = @id", - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.ContentTypeTree)} WHERE {QuoteColumnName("parentContentTypeId")} = @id", - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.ContentTypeTree)} WHERE {QuoteColumnName("childContentTypeId")} = @id", - $@"DELETE FROM {QuoteTableName(PropertyDataDto.TableName)} WHERE {QuoteColumnName("propertyTypeId")} IN - (SELECT id FROM {QuoteTableName(Constants.DatabaseSchema.Tables.PropertyType)} WHERE {QuoteColumnName("contentTypeId")} = @id)", - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.PropertyType)} WHERE {QuoteColumnName("contentTypeId")} = @id", - $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.PropertyTypeGroup)} WHERE {QuoteColumnName("contenttypeNodeId")} = @id", + $"DELETE FROM {QuoteTableName(User2NodeNotifyDto.TableName)} WHERE {QuoteColumnName(User2NodeNotifyDto.NodeIdColumnName)} = @id", + $@"DELETE FROM {QuoteTableName(UserGroup2GranularPermissionDto.TableName)} WHERE {QuoteColumnName(UserGroup2GranularPermissionDto.UniqueIdColumnName)} IN + (SELECT {QuoteColumnName("uniqueId")} FROM {QuoteTableName(NodeDto.TableName)} WHERE {QuoteColumnName(NodeDto.PrimaryKeyColumnName)} = @id)", + $"DELETE FROM {QuoteTableName(TagRelationshipDto.TableName)} WHERE {QuoteColumnName(TagRelationshipDto.PrimaryKeyColumnName)} = @id", + $"DELETE FROM {QuoteTableName(ContentTypeAllowedContentTypeDto.TableName)} WHERE {QuoteColumnName(ContentTypeAllowedContentTypeDto.PrimaryKeyColumnName)} = @id", + $"DELETE FROM {QuoteTableName(ContentTypeAllowedContentTypeDto.TableName)} WHERE {QuoteColumnName(ContentTypeAllowedContentTypeDto.AllowedIdColumnName)} = @id", + $"DELETE FROM {QuoteTableName(ContentType2ContentTypeDto.TableName)} WHERE {QuoteColumnName(ContentType2ContentTypeDto.PrimaryKeyColumnName)} = @id", + $"DELETE FROM {QuoteTableName(ContentType2ContentTypeDto.TableName)} WHERE {QuoteColumnName(ContentType2ContentTypeDto.ChildIdColumnName)} = @id", + $@"DELETE FROM {QuoteTableName(PropertyDataDto.TableName)} WHERE {QuoteColumnName(PropertyDataDto.PropertyTypeIdColumnName)} IN + (SELECT id FROM {QuoteTableName(PropertyTypeDto.TableName)} WHERE {QuoteColumnName(PropertyTypeDto.ContentTypeIdColumnName)} = @id)", + $"DELETE FROM {QuoteTableName(PropertyTypeDto.TableName)} WHERE {QuoteColumnName(PropertyTypeDto.ContentTypeIdColumnName)} = @id", + $"DELETE FROM {QuoteTableName(PropertyTypeGroupDto.TableName)} WHERE {QuoteColumnName(PropertyTypeGroupDto.ContentTypeNodeIdColumnName)} = @id", }; return list; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs index a58d725e0628..2cb25de15504 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs @@ -294,12 +294,15 @@ private Sql SiblingsSql( // the final query for before and after positions will increase. So we need to calculate the offset based on the provided values. int beforeAfterParameterIndexOffset = GetBeforeAfterParameterOffset(objectTypes, filter); + // use all lower case alias names to avoid sql syntax issues + string targetAlias = "target"; + // Find the specific row number of the target node. // We need this to determine the bounds of the row numbers to select. Sql targetRowSql = Sql() .Select("rn") - .From().AppendSubQuery(rowNumberSql, "Target") - .Where(x => x.UniqueId == targetKey, "Target"); + .From().AppendSubQuery(rowNumberSql, targetAlias) + .Where(x => x.UniqueId == targetKey, targetAlias); // We have to reuse the target row sql arguments, however, we also need to add the "before" and "after" values to the arguments. // If we try to do this directly in the params array it'll consider the initial argument array as a single argument. @@ -316,8 +319,8 @@ private Sql SiblingsSql( totalAfter = GetNumberOfSiblingsOutsideSiblingRange(rowNumberSql, targetRowSql, beforeAfterParameterIndex, afterArgumentsArray, false); return Sql() - .Select("UniqueId") - .From().AppendSubQuery(rowNumberSql, "NumberedNodes") + .Select(QuoteColumnName("uniqueId")) + .From().AppendSubQuery(rowNumberSql, "nn") .Where($"rn >= ({targetRowSql.SQL}) - @{beforeAfterParameterIndex}", beforeArgumentsArray) .Where($"rn <= ({targetRowSql.SQL}) + @{beforeAfterParameterIndex}", afterArgumentsArray) .OrderBy("rn"); @@ -355,9 +358,9 @@ private long GetNumberOfSiblingsOutsideSiblingRange( { Sql? sql = Sql() .SelectCount() - .From().AppendSubQuery(rowNumberSql, "NumberedNodes") + .From().AppendSubQuery(rowNumberSql, "nn") .Where($"rn {(getBefore ? "<" : ">")} ({targetRowSql.SQL}) {(getBefore ? "-" : "+")} @{parameterIndex}", arguments); - return Database.ExecuteScalar(sql); + return Database.FirstOrDefault(sql); } @@ -498,14 +501,14 @@ public UmbracoObjectTypes GetObjectType(int id) { Sql sql = Sql().Select(x => x.NodeObjectType).From() .Where(x => x.NodeId == id); - return ObjectTypes.GetUmbracoObjectType(Database.ExecuteScalar(sql)); + return ObjectTypes.GetUmbracoObjectType(Database.First(sql)); } public UmbracoObjectTypes GetObjectType(Guid key) { Sql sql = Sql().Select(x => x.NodeObjectType).From() .Where(x => x.UniqueId == key); - return ObjectTypes.GetUmbracoObjectType(Database.ExecuteScalar(sql)); + return ObjectTypes.GetUmbracoObjectType(Database.First(sql)); } public int ReserveId(Guid key) @@ -972,11 +975,13 @@ private void ApplyOrdering(ref Sql sql, Ordering ordering) orderBy = SqlSyntax.GetQuotedColumn(NodeDto.TableName, "path"); break; case "NODEID": - orderBy = runner.OrderBy; + orderBy = SqlSyntax.GetQuotedColumn(NodeDto.TableName, "id"); orderingIncludesNodeId = true; break; default: - orderBy = QuoteColumnName(runner.OrderBy) ?? string.Empty; + orderBy = runner.OrderBy != null + ? SqlSyntax.GetQuotedColumn(NodeDto.TableName, runner.OrderBy) + : string.Empty; break; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs index ca9d1caf9cd3..ebf4430b6ddc 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs @@ -188,7 +188,7 @@ private ILanguage GetDefault() #region Overrides of RepositoryBase - protected override ILanguage? PerformGet(int id) => PerformGetAll(id).FirstOrDefault(); + protected override ILanguage? PerformGet(int id) => PerformGetAll([id]).FirstOrDefault(); protected override IEnumerable PerformGetAll(params int[]? ids) { @@ -260,15 +260,15 @@ protected override IEnumerable GetDeleteClauses() { // NOTE: There is no constraint between the Language and cmsDictionary/cmsLanguageText tables (?) // but we still need to remove them - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.DictionaryValue)} {lIdWhere}", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.PropertyData)} {lIdWhere}", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation)} {lIdWhere}", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.DocumentCultureVariation)} {lIdWhere}", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.TagRelationship)} WHERE {QuoteColumnName("tagId")} IN (SELECT id FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.Tag)} {lIdWhere})", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.Tag)} {lIdWhere}", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.DocumentUrl)} {lIdWhere}", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.DocumentUrlAlias)} {lIdWhere}", - $"DELETE FROM {SqlSyntax.GetQuotedName(Constants.DatabaseSchema.Tables.Language)} WHERE id = @id", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.DictionaryValue)} {lIdWhere}", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.PropertyData)} {lIdWhere}", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation)} {lIdWhere}", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.DocumentCultureVariation)} {lIdWhere}", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.TagRelationship)} WHERE {QuoteColumnName("tagId")} IN (SELECT id FROM {QuoteName(Constants.DatabaseSchema.Tables.Tag)} {lIdWhere})", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.Tag)} {lIdWhere}", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.DocumentUrl)} {lIdWhere}", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.DocumentUrlAlias)} {lIdWhere}", + $"DELETE FROM {QuoteName(Constants.DatabaseSchema.Tables.Language)} WHERE id = @id", }; return list; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LastSyncedRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LastSyncedRepository.cs index 4458c04e2b4f..dc7f92f78a3d 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LastSyncedRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LastSyncedRepository.cs @@ -1,4 +1,4 @@ -using NPoco; +using NPoco; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Factories; using Umbraco.Cms.Core.Persistence.Repositories; @@ -58,7 +58,7 @@ public async Task SaveInternalIdAsync(int id) await Database.InsertOrUpdateAsync( dto, - "SET lastSyncedInternalId=@LastSyncedInternalId, lastSyncedDate=@LastSyncedDate WHERE machineId=@MachineId", + $"SET {QuoteColumnName("lastSyncedInternalId")}=@LastSyncedInternalId, {QuoteColumnName("lastSyncedDate")}=@LastSyncedDate WHERE {QuoteColumnName("machineId")}=@MachineId", new { dto.LastSyncedInternalId, @@ -79,7 +79,7 @@ public async Task SaveExternalIdAsync(int id) await Database.InsertOrUpdateAsync( dto, - "SET lastSyncedExternalId=@LastSyncedExternalId, lastSyncedDate=@LastSyncedDate WHERE machineId=@MachineId", + $"SET {QuoteColumnName("lastSyncedExternalId")}=@LastSyncedExternalId, {QuoteColumnName("lastSyncedDate")}=@LastSyncedDate WHERE {QuoteColumnName("machineId")}=@MachineId", new { dto.LastSyncedExternalId, @@ -91,11 +91,11 @@ await Database.InsertOrUpdateAsync( /// public async Task DeleteEntriesOlderThanAsync(DateTime pruneDate) { - var maxId = Database.ExecuteScalar($"SELECT MAX(Id) FROM umbracoCacheInstruction;"); + var maxId = Database.ExecuteScalar($"SELECT MAX(Id) FROM {QuoteTableName("umbracoCacheInstruction")};"); Sql sql = new Sql().Append( - @"DELETE FROM umbracoLastSynced WHERE lastSyncedDate < @pruneDate OR lastSyncedInternalId > @maxId AND lastSyncedExternalId > @maxId;", + @$"DELETE FROM {QuoteTableName("umbracoLastSynced")} WHERE {QuoteColumnName("lastSyncedDate")} < @pruneDate OR {QuoteColumnName("lastSyncedInternalId")} > @maxId AND {QuoteColumnName("lastSyncedExternalId")} > @maxId;", new { pruneDate, maxId }); await Database.ExecuteAsync(sql); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs index 46cfcff0ac5d..aee398819af5 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs @@ -375,7 +375,7 @@ protected override IEnumerable GetDeleteClauses() $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.Document)} WHERE {nodeId} = @id", $@"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.MediaVersion)} WHERE id IN (SELECT id FROM {QuoteTableName(Constants.DatabaseSchema.Tables.ContentVersion)} WHERE {nodeId} = @id)", - $@"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.PropertyData)} WHERE versionId IN + $@"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.PropertyData)} WHERE {QuoteColumnName("versionId")} IN (SELECT id FROM {QuoteTableName(Constants.DatabaseSchema.Tables.ContentVersion)} WHERE {nodeId} = @id)", $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.ContentVersion)} WHERE {nodeId} = @id", $"DELETE FROM {QuoteTableName(Constants.DatabaseSchema.Tables.Content)} WHERE {nodeId} = @id", diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs index 3ea46925011c..2d01a27ce4c8 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs @@ -224,13 +224,15 @@ public IEnumerable GetByMemberGroup(string groupName) return Enumerable.Empty(); } - Sql subQuery = Sql().Select("Member").From() + Sql subQuery = Sql() + .Select(c => c.Member) + .From() .Where(dto => dto.MemberGroup == memberGroup.Id); Sql sql = GetBaseQuery(false) // TODO: An inner join would be better, though I've read that the query optimizer will always turn a // subquery with an IN clause into an inner join anyways. - .Append("WHERE umbracoNode.id IN (" + subQuery.SQL + ")", subQuery.Arguments) + .Append($"WHERE {QuoteTableName("umbracoNode")}.id IN (" + subQuery.SQL + ")", subQuery.Arguments) .OrderByDescending(x => x.VersionDate) .OrderBy(x => x.SortOrder); @@ -255,7 +257,7 @@ public int GetCountByQuery(IQuery? query) //get the COUNT base query Sql fullSql = GetBaseQuery(true) - .Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments)); + .Append(new Sql($"WHERE {QuoteTableName("umbracoNode")}.id IN ({sql.SQL})", sql.Arguments)); return Database.ExecuteScalar(fullSql); } @@ -318,7 +320,7 @@ public async Task> GetPagedByFilterAsync(MemberFilter member } var pageIndex = skip / take; - Page? pageResult = await Database.PageAsync(pageIndex+1, take, sql); + Page? pageResult = await Database.PageAsync(pageIndex + 1, take, sql); // shortcut so our join is not too big, but we also hope these are cached, so we don't have to map them again. var nodeIds = pageResult.Items.Select(x => x.NodeId).ToArray(); @@ -409,16 +411,12 @@ public int[] GetMemberIds(string[] usernames) Guid memberObjectType = Constants.ObjectTypes.Member; Sql memberSql = Sql() - .Select("umbracoNode.id") + .Select(n => n.NodeId) .From() .InnerJoin() .On(dto => dto.NodeId, dto => dto.NodeId) .Where(x => x.NodeObjectType == memberObjectType) - .Where("cmsMember.LoginName in (@usernames)", new - { - /*usernames =*/ - usernames - }); + .WhereIn(m => m.LoginName, usernames); return Database.Fetch(memberSql).ToArray(); } @@ -553,7 +551,7 @@ private IMember MapDtoToContent(MemberDto dto) var versionId = dto.ContentVersionDto.Id; var temp = new TempContent(dto.ContentDto.NodeId, versionId, 0, memberType); IDictionary properties = - GetPropertyCollections(new List> {temp}); + GetPropertyCollections(new List> { temp }); member.Properties = properties[versionId]; // reset dirty initial properties (U4-1946) @@ -616,7 +614,7 @@ protected override IEnumerable PerformGetByQuery(IQuery query) var translator = new SqlTranslator(sqlWithProps, query); Sql sql = translator.Translate(); - baseQuery.Append("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments) + baseQuery.Append($"WHERE {QuoteTableName("umbracoNode")}.id IN (" + sql.SQL + ")", sql.Arguments) .OrderBy(x => x.SortOrder); return MapDtosToContent(Database.Fetch(baseQuery)); @@ -766,8 +764,11 @@ public override IEnumerable GetAllVersions(int nodeId) protected override void PerformDeleteVersion(int id, int versionId) { - Database.Delete("WHERE versionId = @VersionId", new {versionId}); - Database.Delete("WHERE versionId = @VersionId", new {versionId}); + Sql sql = Sql().Delete(x => x.VersionId == versionId); + Database.Execute(sql); + + sql = Sql().Delete(x => x.Id == versionId); + Database.Execute(sql); } #endregion diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberTypeRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberTypeRepository.cs index 9a1ff64f424a..bf0ab3235cdd 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberTypeRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberTypeRepository.cs @@ -144,9 +144,9 @@ private Sql GetSubquery() protected override IEnumerable GetDeleteClauses() { var l = (List)base.GetDeleteClauses(); // we know it's a list - l.Add($"DELETE FROM {QuoteTableName("cmsMemberType")} WHERE NodeId = @id"); - l.Add($"DELETE FROM {QuoteTableName("cmsContentType")} WHERE nodeId = @id"); - l.Add($"DELETE FROM {QuoteTableName("umbracoNode")} WHERE id = @id"); + l.Add($"DELETE FROM {QuoteTableName(MemberPropertyTypeDto.TableName)} WHERE {QuoteColumnName(MemberPropertyTypeDto.NodeIdColumnName)} = @id"); + l.Add($"DELETE FROM {QuoteTableName(ContentTypeDto.TableName)} WHERE {QuoteColumnName(ContentTypeDto.NodeIdColumnName)} = @id"); + l.Add($"DELETE FROM {QuoteTableName(NodeDto.TableName)} WHERE id = @id"); return l; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs index 985e0ac63691..2490cb6b1c96 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs @@ -159,12 +159,7 @@ public IEnumerable GetAllUrls(int rootContentId, long pageIndex, i public IEnumerable SearchUrls(string searchTerm, long pageIndex, int pageSize, out long total) { Sql sql = GetBaseQuery(false) - .Where( - string.Format( - "{0}.{1} LIKE @url", - QuoteTableName("umbracoRedirectUrl"), - QuoteColumnName("Url")), - new { url = "%" + searchTerm.Trim().ToLowerInvariant() + "%" }) + .WhereLike(x => x.Url, "%" + searchTerm.Trim().ToLowerInvariant() + "%") .OrderByDescending(x => x.CreateDateUtc); Page result = Database.Page(pageIndex + 1, pageSize, sql); total = Convert.ToInt32(result.TotalItems); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RepositoryBase.cs index ee20a8cccfb3..9f2715dc9289 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RepositoryBase.cs @@ -88,4 +88,18 @@ protected IScope AmbientScope /// Quotes a column name according to the registered SQL syntax provider. /// protected string QuoteColumnName(string? columnName) => SqlSyntax.GetQuotedColumnName(columnName); + + /// + /// Returns the column name, qualified by the specified table name, with appropriate quoting for use in SQL + /// statements. + /// + /// The name of the table to qualify the column with. Cannot be null or empty. + /// The name of the column to quote. Cannot be null or empty. + /// A string containing the quoted and qualified column name suitable for use in SQL queries. + protected string QuoteColumnName(string tableName, string columnName) => SqlSyntax.GetQuotedColumn(tableName, columnName); + + /// + /// Quotes a column name according to the registered SQL syntax provider. + /// + protected string QuoteName(string? name) => SqlSyntax.GetQuotedName(name); } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs index d78502630780..2129142b3322 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs @@ -152,7 +152,7 @@ public void Assign(int contentId, int propertyTypeId, IEnumerable tags, bo FROM {tagSetSql} LEFT OUTER JOIN {cmsTags} ON (LOWER(tagset.tag) = LOWER({cmsTags}.tag) AND LOWER(tagset.{group}) = LOWER({cmsTags}.{group}) AND COALESCE(tagset.languageid, -1) = COALESCE({cmsTagsLanguageIdCol}, -1)) -WHERE {cmsTags}.id IS NULL"; // cmsTags.id is never null +WHERE {cmsTags}.id IS NULL"; Database.Execute(sql1); @@ -160,13 +160,13 @@ LEFT OUTER JOIN {cmsTags} var sql2 = $@"INSERT INTO {QuoteTableName(TagRelationshipDto.TableName)} ({nodeId}, {QuoteColumnName("propertyTypeId")}, {QuoteColumnName("tagId")}) SELECT {contentId}, {propertyTypeId}, tagset2.Id FROM ( - SELECT t.{QuoteColumnName("Id")} + SELECT t.id FROM {tagSetSql} INNER JOIN {cmsTags} as t ON (LOWER(tagset.tag) = LOWER(t.tag) AND LOWER(tagset.{group}) = LOWER(t.{group}) AND COALESCE(tagset.languageid, -1) = COALESCE(t.{languageIdCol}, -1)) ) AS tagset2 LEFT OUTER JOIN {QuoteTableName(TagRelationshipDto.TableName)} r -ON (tagset2.id = r.{QuoteColumnName("tagId")} AND r.{nodeId} = {contentId} AND r.{QuoteColumnName("propertyTypeID")} = {propertyTypeId}) -WHERE r.{QuoteColumnName("tagId")} IS NULL"; // cmsTagRelationship.tagId is never null +ON (tagset2.id = r.{QuoteColumnName("tagId")} AND r.{nodeId} = {contentId} AND r.{QuoteColumnName("propertyTypeId")} = {propertyTypeId}) +WHERE r.{QuoteColumnName("tagId")} IS NULL"; Database.Execute(sql2); } @@ -256,7 +256,7 @@ private string GetTagSet(IEnumerable tags) } else { - sql.Append("NULL"); + sql.Append("NULL" + SqlSyntax.GetNullCastSuffix()); } sql.Append(" AS languageid"); } @@ -452,7 +452,8 @@ public IEnumerable GetTagsForEntityType( } sql = sql - .GroupBy(x => x.Id, x => x.Text, x => x.Group, x => x.LanguageId); + .GroupBy(x => x.Id, x => x.Text, x => x.Group, x => x.LanguageId) + .OrderBy(o => o.Text); return ExecuteTagsQuery(sql); } @@ -473,6 +474,9 @@ public IEnumerable GetTagsForEntity(int contentId, string? group = null, s .Where(dto => dto.Group == group); } + sql = sql + .OrderBy(o => o.Text); + return ExecuteTagsQuery(sql); } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs index 16b13612a515..33dc2c2f8f3c 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs @@ -68,7 +68,7 @@ private IEnumerable GetPagedRelations( return []; } - ISqlSyntaxProvider? sx = _scopeAccessor.AmbientScope.Database.SqlContext.SqlSyntax; + ISqlSyntaxProvider sx = _scopeAccessor.AmbientScope.Database.SqlContext.SqlSyntax; string[] columns = [ sx.ColumnWithAlias("x", "otherId", "nodeId"), sx.ColumnWithAlias("n", "uniqueId", "nodeKey"), diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs index 2a5e31d50f2c..292ba3bfd4e2 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs @@ -492,7 +492,7 @@ protected override IEnumerable GetDeleteClauses() { var userGroupId = QuoteColumnName("userGroupId"); var userGroupKey = QuoteColumnName("userGroupKey"); - var key = QuoteColumnName("Key"); + var key = QuoteColumnName(UserGroupDto.KeyColumnName); var umbracoUserGroup = QuoteTableName(UserGroupDto.TableName); var list = new List { diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index 1de89e8a09fe..8db0246b7b61 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -1133,105 +1133,7 @@ public IEnumerable GetPagedResultsByQuery( UserState[]? userState = null, IQuery? filter = null) { - if (orderBy == null) - { - throw new ArgumentNullException(nameof(orderBy)); - } - - Sql? filterSql = null; - Tuple[]? customFilterWheres = filter?.GetWhereClauses().ToArray(); - var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0; - if (hasCustomFilter - || (includeUserGroups != null && includeUserGroups.Length > 0) - || (excludeUserGroups != null && excludeUserGroups.Length > 0) - || (userState != null && userState.Length > 0 && userState.Contains(UserState.All) == false)) - { - filterSql = SqlContext.Sql(); - } - - if (hasCustomFilter) - { - foreach (Tuple clause in customFilterWheres!) - { - filterSql?.Append($"AND ({clause.Item1})", clause.Item2); - } - } - - var userIdQuoted = SqlSyntax.GetQuotedColumn("umbracoUser", "id"); - if (includeUserGroups != null && includeUserGroups.Length > 0) - { - string subQuery = GetSuQueryInExclude("IN"); - filterSql?.Append(subQuery, new { userGroups = includeUserGroups }); - } - - if (excludeUserGroups != null && excludeUserGroups.Length > 0) - { - string subQuery = GetSuQueryInExclude("NOT IN"); - filterSql?.Append(subQuery, new { userGroups = excludeUserGroups }); - } - - if (userState != null && userState.Length > 0) - { - //the "ALL" state doesn't require any filtering so we ignore that, if it exists in the list we don't do any filtering - if (userState.Contains(UserState.All) == false) - { - var sb = new StringBuilder("("); - var appended = false; - - if (userState.Contains(UserState.Active)) - { - sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL)"); - appended = true; - } - - if (userState.Contains(UserState.Inactive)) - { - if (appended) - { - sb.Append(" OR "); - } - - sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL)"); - appended = true; - } - - if (userState.Contains(UserState.Disabled)) - { - if (appended) - { - sb.Append(" OR "); - } - - sb.Append("(userDisabled = 1)"); - appended = true; - } - - if (userState.Contains(UserState.LockedOut)) - { - if (appended) - { - sb.Append(" OR "); - } - - sb.Append("(userNoConsole = 1)"); - appended = true; - } - - if (userState.Contains(UserState.Invited)) - { - if (appended) - { - sb.Append(" OR "); - } - - sb.Append("(lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL)"); - appended = true; - } - - sb.Append(")"); - filterSql?.Append("AND " + sb); - } - } + ArgumentNullException.ThrowIfNull(orderBy); // create base query Sql sql = SqlContext.Sql() @@ -1244,9 +1146,12 @@ public IEnumerable GetPagedResultsByQuery( sql = new SqlTranslator(sql, query).Translate(); } - // get sorted and filtered sql + // get filtered sql + Sql filteredSql = ApplyFilter(sql, query, includeUserGroups, excludeUserGroups, userState, filter); + + // get sorted sql Sql sqlNodeIdsWithSort = - ApplySort(ApplyFilter(sql, filterSql, query != null), orderBy, orderDirection); + ApplySort(filteredSql, orderBy, orderDirection); // get a page of results and total count Page? pagedResult = Database.Page(pageIndex + 1, pageSize, sqlNodeIdsWithSort); @@ -1264,10 +1169,10 @@ private string GetSuQueryInExclude(string inOrNotIn) return @$"AND ({userIdQuoted} {inOrNotIn} (SELECT DISTINCT {userIdQuoted} FROM {QuoteTableName("umbracoUser")} INNER JOIN {QuoteTableName("umbracoUser2UserGroup")} - ON {SqlSyntax.GetQuotedColumn("umbracoUser2UserGroup", "userId")} = {userIdQuoted} + ON {QuoteColumnName("umbracoUser2UserGroup", "userId")} = {userIdQuoted} INNER JOIN {QuoteTableName("umbracoUserGroup")} - ON {SqlSyntax.GetQuotedColumn("umbracoUserGroup", "id")} = {SqlSyntax.GetQuotedColumn("umbracoUser2UserGroup", "userGroupId")} - WHERE {SqlSyntax.GetQuotedColumn("umbracoUserGroup", "userGroupAlias")} IN (@userGroups)))"; + ON {QuoteColumnName("umbracoUserGroup", "id")} = {QuoteColumnName("umbracoUser2UserGroup", "userGroupId")} + WHERE {QuoteColumnName("umbracoUserGroup", "userGroupAlias")} IN (@userGroups)))"; } public IEnumerable GetAllClientIds() @@ -1303,16 +1208,17 @@ public bool RemoveClientId(int id, string clientId) return Get(userId); } - private Sql ApplyFilter(Sql sql, Sql? filterSql, bool hasWhereClause) + private Sql ApplyFilter(Sql sql, IQuery? query, string[]? includeUserGroups, string[]? excludeUserGroups, UserState[]? userState, IQuery? filter) { + Sql? filterSql = PrepareFilterSql(includeUserGroups, excludeUserGroups, userState, filter); if (filterSql == null) { return sql; } - //ensure we don't append a WHERE if there is already one + // ensure we don't append a WHERE if there is already one var args = filterSql.Arguments; - var sqlFilter = hasWhereClause + var sqlFilter = query != null ? filterSql.SQL : " WHERE " + filterSql.SQL.TrimStart("AND "); @@ -1394,5 +1300,134 @@ public void InvalidateSessionsForRemovedProviders(IEnumerable currentLog Database.Execute($"DELETE FROM {QuoteTableName("umbracoOpenIddictTokens")} WHERE {QuoteColumnName("Subject")} IN ('{userKeysForInClause}')"); } + private Sql? PrepareFilterSql(string[]? includeUserGroups, string[]? excludeUserGroups, UserState[]? userState, IQuery? filter) + { + Sql? filterSql = null; + + Tuple[]? customFilterWheres = filter?.GetWhereClauses().ToArray(); + var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0; + if (hasCustomFilter + || (includeUserGroups != null && includeUserGroups.Length > 0) + || (excludeUserGroups != null && excludeUserGroups.Length > 0) + || (userState != null && userState.Length > 0 && userState.Contains(UserState.All) == false)) + { + filterSql = SqlContext.Sql(); + + if (hasCustomFilter) + { + foreach (Tuple clause in customFilterWheres!) + { + filterSql.Append($"AND ({clause.Item1})", clause.Item2); + } + } + + FilterByIncludedUserGroups(includeUserGroups, filterSql); + + FilterByExcludedUserGroups(excludeUserGroups, filterSql); + + FilterByUserState(userState, filterSql); + } + + return filterSql; + } + + private void FilterByIncludedUserGroups(string[]? includeUserGroups, Sql filterSql) + { + if (includeUserGroups != null && includeUserGroups.Length > 0) + { + string subQuery = GetSuQueryInExclude("IN"); + filterSql.Append(subQuery, new { userGroups = includeUserGroups }); + } + } + + private void FilterByExcludedUserGroups(string[]? excludeUserGroups, Sql filterSql) + { + if (excludeUserGroups != null && excludeUserGroups.Length > 0) + { + string subQuery = GetSuQueryInExclude("NOT IN"); + filterSql.Append(subQuery, new { userGroups = excludeUserGroups }); + } + } + + /// + /// Appends user state filtering conditions to the specified SQL filter based on the provided user states. + /// + /// If multiple user states are specified, the resulting filter will match users in any of the + /// given states. The method does not modify the filter if no applicable user states are provided. + /// An array of user states to filter by. If null, empty, or contains the 'All' state, no filtering is applied. + /// The SQL filter to which the user state conditions are appended. If null, no conditions are added. + private void FilterByUserState(UserState[]? userState, Sql filterSql) + { + if (userState != null && userState.Length > 0) + { + // the "ALL" state doesn't require any filtering so we ignore that, if it exists in the list we don't do any filtering + if (userState.Contains(UserState.All) == false) + { + var sb = new StringBuilder("("); + var appended = false; + var userDisabled = QuoteColumnName("userDisabled"); + var userNoConsole = QuoteColumnName("userNoConsole"); + var lastLoginDate = QuoteColumnName("lastLoginDate"); + var invitedDate = QuoteColumnName("invitedDate"); + + var falseValue = SqlSyntax.ConvertIntegerToBoolean(0); + var trueValue = SqlSyntax.ConvertIntegerToBoolean(1); + if (userState.Contains(UserState.Active)) + { + sb.Append($"({userDisabled} = {falseValue} AND {userNoConsole} = {falseValue} AND {lastLoginDate} IS NOT NULL)"); + appended = true; + } + + if (userState.Contains(UserState.Inactive)) + { + if (appended) + { + sb.Append(" OR "); + } + + sb.Append($"({userDisabled} = {falseValue} AND {userNoConsole} = {falseValue} AND {lastLoginDate} IS NULL)"); + appended = true; + } + + if (userState.Contains(UserState.Disabled)) + { + if (appended) + { + sb.Append(" OR "); + } + + sb.Append($"({userDisabled} = {trueValue})"); + appended = true; + } + + if (userState.Contains(UserState.LockedOut)) + { + if (appended) + { + sb.Append(" OR "); + } + + sb.Append($"({userNoConsole} = {trueValue})"); + appended = true; + } + + if (userState.Contains(UserState.Invited)) + { + if (appended) + { + sb.Append(" OR "); + } + + sb.Append($"({lastLoginDate} IS NULL AND {userDisabled} = {trueValue} AND {invitedDate} IS NOT NULL)"); + appended = true; + } + + sb.Append(")"); + + filterSql.Append("AND " + sb); + } + } + } + #endregion } diff --git a/src/Umbraco.Infrastructure/Persistence/SqlSyntaxExtensions.cs b/src/Umbraco.Infrastructure/Persistence/SqlSyntaxExtensions.cs index 57ab9a6edaf9..61d15d23e734 100644 --- a/src/Umbraco.Infrastructure/Persistence/SqlSyntaxExtensions.cs +++ b/src/Umbraco.Infrastructure/Persistence/SqlSyntaxExtensions.cs @@ -30,7 +30,7 @@ public static string GetFieldName(this ISqlSyntaxProvider sqlSyntax, Expre return sqlSyntax.GetQuotedTableName(tableName) + "." + sqlSyntax.GetQuotedColumnName(fieldName); } - private static string GetColumnName(this PropertyInfo column) + internal static string GetColumnName(this PropertyInfo column) { ColumnAttribute? attr = column.FirstAttribute(); return string.IsNullOrWhiteSpace(attr?.Name) ? column.Name : attr.Name; diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs index 5ef99e9b540d..11804af7f3b6 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs @@ -97,7 +97,7 @@ public UmbracoDatabaseFactory( #endregion - private DbProviderFactory? DbProviderFactory + protected DbProviderFactory? DbProviderFactory { get { @@ -281,7 +281,7 @@ private InitializedPocoDataBuilder GetPocoDataFactoryResolver(Type type, IPocoDa => new UmbracoPocoDataBuilder(type, _pocoMappers, _upgrading).Init(); // method used by NPoco's UmbracoDatabaseFactory to actually create the database instance - private UmbracoDatabase? CreateDatabaseInstance() + protected virtual UmbracoDatabase? CreateDatabaseInstance() { if (ConnectionString is null || SqlContext is null || DbProviderFactory is null) { diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ExecuteScalarVsFirstOrDefaultTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ExecuteScalarVsFirstOrDefaultTests.cs new file mode 100644 index 000000000000..715d7436104b --- /dev/null +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ExecuteScalarVsFirstOrDefaultTests.cs @@ -0,0 +1,103 @@ +using NPoco; +using NUnit.Framework; +using Umbraco.Cms.Core.Scoping; +using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax; +using Umbraco.Cms.Tests.Common.Testing; +using Umbraco.Cms.Tests.Integration.Testing; + +namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositories; + +/// +/// Tests demonstrating the difference between ExecuteScalar and FirstOrDefault in NPoco. +/// +/// +/// ExecuteScalar does not invoke all ISqlSyntaxProvider mappers, which causes failures +/// on database providers like PostgreSQL where type conversions require the full mapper pipeline. +/// See: https://github.com/umbraco/Umbraco-CMS/issues/21448 +/// +[TestFixture] +[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] +internal sealed class ExecuteScalarVsFirstOrDefaultTests : UmbracoIntegrationTest +{ + /// + /// Verifies that ExecuteScalarAsync fails to properly map COUNT(*) to long on certain database providers. + /// + /// + /// This test may pass on SQLite/SQL Server but fails on PostgreSQL because ExecuteScalar + /// bypasses the ISqlSyntaxProvider mapper pipeline. PostgreSQL returns int8 for COUNT(*) + /// which requires proper type mapping to convert to C# long. + /// + /// The fix is to use FirstOrDefaultAsync instead, which goes through the full mapper pipeline. + /// + [Test] + public async Task ExecuteScalarAsync_CountQuery_FailsOnPostgreSqlDueToMissingMapperInvocation() + { + // Arrange + using ICoreScope scope = ScopeProvider.CreateCoreScope(); + IUmbracoDatabase database = ScopeAccessor.AmbientScope!.Database; + ISqlSyntaxProvider syntax = database.SqlContext.SqlSyntax; + + var sql = new Sql($"SELECT COUNT(*) FROM {syntax.GetQuotedTableName("umbracoNode")}"); + + // Act & Assert + // On PostgreSQL, this throws because ExecuteScalar doesn't invoke ISqlSyntaxProvider mappers. + // On SQLite/SQL Server, this may succeed due to compatible type handling. + // The proper fix is to use FirstOrDefaultAsync instead. + try + { + var count = await database.ExecuteScalarAsync(sql); + + // If we reach here, the database provider handles the type conversion natively. + // This is the case for SQLite and SQL Server. + // For PostgreSQL, this line is never reached - an exception is thrown above. + Assert.That(count, Is.GreaterThanOrEqualTo(0), "Count should be non-negative"); + + // Log a warning that this test passed - it demonstrates the issue only fails on PostgreSQL + TestContext.WriteLine( + "WARNING: ExecuteScalarAsync succeeded on this database provider. " + + "This test demonstrates a failure that occurs on PostgreSQL where ISqlSyntaxProvider " + + "mappers are not invoked by ExecuteScalar, causing type conversion failures."); + } + catch (InvalidCastException ex) + { + // This is the expected failure on PostgreSQL - the type cannot be cast without proper mapping + Assert.Pass($"ExecuteScalarAsync failed as expected on this database provider: {ex.Message}"); + } + catch (Exception ex) when (ex.Message.Contains("cast") || ex.Message.Contains("convert")) + { + // Other type conversion errors that indicate the mapper issue + Assert.Pass($"ExecuteScalarAsync failed with type conversion error as expected: {ex.Message}"); + } + + scope.Complete(); + } + + /// + /// Verifies that FirstOrDefaultAsync correctly maps COUNT(*) to long on all database providers. + /// + /// + /// Unlike ExecuteScalar, FirstOrDefault goes through the full NPoco mapper pipeline, + /// including ISqlSyntaxProvider mappers, ensuring proper type conversion on all database providers. + /// + [Test] + public async Task FirstOrDefaultAsync_CountQuery_SucceedsOnAllDatabaseProviders() + { + // Arrange + using ICoreScope scope = ScopeProvider.CreateCoreScope(); + IUmbracoDatabase database = ScopeAccessor.AmbientScope!.Database; + ISqlSyntaxProvider syntax = database.SqlContext.SqlSyntax; + + var sql = new Sql($"SELECT COUNT(*) FROM {syntax.GetQuotedTableName("umbracoNode")}"); + + // Act + // FirstOrDefaultAsync invokes the full mapper pipeline, including ISqlSyntaxProvider mappers. + // This ensures proper type conversion on all database providers including PostgreSQL. + var count = await database.FirstOrDefaultAsync(sql); + + // Assert + Assert.That(count, Is.GreaterThanOrEqualTo(0), "Count should be non-negative"); + + scope.Complete(); + } +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs index dd6cfb6c494b..279c0958e486 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs @@ -41,4 +41,103 @@ public void DatabaseSchemaCreation_Produces_DatabaseSchemaResult_With_Zero_Error // Assert Assert.That(result.Errors.Count, Is.EqualTo(0)); } + + [Test] + public void Validate_DatabaseSchemaResult_with_CustomTables_has_Errors() + { + if (!IsSQLiteDatabase()) + { + Assert.Ignore("This test is only valid for SQLite databases."); + return; + } + + DatabaseSchemaResult result; + DatabaseSchemaCreator schema; + + using (ScopeProvider.CreateScope(autoComplete: true)) + { + schema = new DatabaseSchemaCreator( + ScopeAccessor.AmbientScope.Database, + LoggerFactory.CreateLogger(), + LoggerFactory, + UmbracoVersion, + EventAggregator, + Mock.Of>(x => + x.CurrentValue == new InstallDefaultDataSettings())); + schema.InitializeDatabaseSchema(); + } + + // add some custom tables with columns, indexes, constraints, etc. + CreateCustomTables(); + + using (ScopeProvider.CreateScope(autoComplete: true)) + { + result = schema.ValidateSchema(DatabaseSchemaCreator._orderedTables); + } + + // Assert + Assert.That(result.Errors.Count, Is.EqualTo(11)); + + var expectedErrors = new List>() + { + Tuple.Create("Table", "customTable"), + Tuple.Create("Column", "customTable,id"), + Tuple.Create("Column", "customTable,name"), + Tuple.Create("Index", "IX_customTable_name"), + Tuple.Create("Constraint", "PK_customTable"), + Tuple.Create("Table", "customTableFK"), + Tuple.Create("Column", "customTableFK,id"), + Tuple.Create("Column", "customTableFK,customTableId"), + Tuple.Create("Column", "customTableFK,name"), + Tuple.Create("Unknown", "CFK_customTableFK_id"), + Tuple.Create("Constraint", "PK_customTableFK"), + }; + foreach (var expectedError in expectedErrors) + { + Assert.That(result.Errors.Contains(expectedError), Is.True); + } + } + + private bool IsSQLiteDatabase() + { + using (ScopeProvider.CreateScope(autoComplete: true)) + { + return ScopeAccessor.AmbientScope.Database.SqlContext.DatabaseType is NPoco.DatabaseTypes.SQLiteDatabaseType; + } + } + + /// + /// Creates 'customTable' and 'customTableFK' tables in the specified Umbraco database. + /// + /// + /// This method is used to create custom tables for testing purposes only. + /// + private void CreateCustomTables() + { + using (ScopeProvider.CreateScope(autoComplete: true)) + { + string q(string name) => ScopeAccessor.AmbientScope.Database.SqlContext + .SqlSyntax.GetQuotedName(name); + + ScopeAccessor.AmbientScope.Database + .Execute(@$" +CREATE TABLE {q("customTable")} ( + {q("id")} INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + {q("name")} NVARCHAR(255) +)"); + + ScopeAccessor.AmbientScope.Database + .Execute("CREATE INDEX IX_customTable_name ON customTable (name)"); + + ScopeAccessor.AmbientScope.Database + .Execute(@$" +CREATE TABLE {q("customTableFK")} +( + {q("id")} INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + {q("customTableId")} INT NOT NULL, + {q("name")} NVARCHAR(255), + CONSTRAINT CFK_customTableFK_id FOREIGN KEY ({q("customTableId")}) REFERENCES {q("customTable")} ({q("id")}) +)"); + } + } } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/NPocoTests/NPocoSqlExtensionsTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/NPocoTests/NPocoSqlExtensionsTests.cs index a9aac06f0aa1..18286f0b7ec5 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/NPocoTests/NPocoSqlExtensionsTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/NPocoTests/NPocoSqlExtensionsTests.cs @@ -120,13 +120,11 @@ public void WhereInValueFieldTest() [Test] public void WhereInObjectFieldTest() { - // this test used to fail because x => x.Text was evaluated as a lambda - // and returned "[umbracoNode].[text] = @0"... had to fix WhereIn. var sql = new Sql(SqlContext) .Select("*") .From() .WhereIn(x => x.Text, new[] { "a", "b", "c" }); - Assert.AreEqual("SELECT *\nFROM [umbracoNode]\nWHERE ([umbracoNode].[text] IN (@0,@1,@2))", sql.SQL); + Assert.AreEqual("SELECT *\nFROM [umbracoNode]\nWHERE (LOWER([umbracoNode].[text]) IN (@0,@1,@2))", sql.SQL); } [Test]