diff --git a/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs
index d2c7aa87ff..71880c95dc 100644
--- a/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs
+++ b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs
@@ -29,6 +29,20 @@ namespace Umbraco.Extensions
return sql.Where(s, a);
}
+ ///
+ /// Adds a WHERE clause to the SQL query based on the specified predicate and optional alias, and appends a
+ /// closing parenthesis to the query. This is used for selects within "WHERE [column] IN (SELECT ...)" statements.
+ ///
+ /// The type of the data transfer object (DTO) used to define the predicate.
+ /// The SQL query to which the WHERE clause will be added.
+ /// An expression that defines the condition for the WHERE clause.
+ /// An optional alias to qualify the table or entity in the query. If null, no alias is used.
+ /// The modified SQL query with the appended WHERE clause and closing parenthesis.
+ public static Sql WhereClosure(this Sql sql, Expression> predicate, string? alias = null)
+ {
+ return sql.Where(predicate, alias).Append(")");
+ }
+
///
/// Appends a WHERE clause to the Sql statement.
///
@@ -74,7 +88,7 @@ namespace Umbraco.Extensions
public static Sql WhereIn(this Sql sql, Expression> field, IEnumerable? values)
{
var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(field);
- sql.Where(fieldName + " IN (@values)", new { values });
+ sql.Where($"{fieldName} IN (@values)", new { values });
return sql;
}
@@ -112,29 +126,41 @@ namespace Umbraco.Extensions
return sql.WhereIn(field, values, false, tableAlias);
}
-
- public static Sql WhereLike(this Sql sql, Expression> fieldSelector, Sql? valuesSql)
+ ///
+ /// This builds a WHERE clause with a LIKE statement where the value is built from a subquery.
+ /// E.g. for SQL Server: WHERE [field] LIKE CONCAT((SELECT [value] FROM ...), '%').
+ /// Or SQLite : WHERE [field] LIKE ((SELECT [value] FROM ...) || '%').
+ ///
+ /// The type of the Dto.
+ /// The Sql statement.
+ /// An expression specifying the field.
+ /// The sql object to select the values.
+ /// If ommitted or empty the specific wildcard char is used as suffix for the resulting values from valueSql query.
+ ///
+ public static Sql WhereLike(this Sql sql, Expression> fieldSelector, Sql? valuesSql, string concatDefault = "")
{
var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(fieldSelector);
- sql.Where(fieldName + " LIKE (" + valuesSql?.SQL + ")", valuesSql?.Arguments);
+ var concat = sql.SqlContext.SqlSyntax.GetWildcardConcat(concatDefault);
+ var likeSelect = sql.SqlContext.SqlSyntax.GetConcat(valuesSql?.SQL ?? string.Empty, concat);
+ sql.Where($"{fieldName} LIKE {likeSelect}", valuesSql?.Arguments);
return sql;
}
public static Sql Union(this Sql sql, Sql sql2)
{
- return sql.Append( " UNION ").Append(sql2);
+ return sql.Append(" UNION ").Append(sql2);
}
public static Sql.SqlJoinClause InnerJoinNested(this Sql sql, Sql nestedQuery, string alias)
{
return new Sql.SqlJoinClause(sql.Append("INNER JOIN (").Append(nestedQuery)
- .Append($") [{alias}]"));
+ .Append($") {sql.SqlContext.SqlSyntax.GetQuotedName(alias)}"));
}
public static Sql WhereLike(this Sql sql, Expression> fieldSelector, string likeValue)
{
var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(fieldSelector);
- sql.Where(fieldName + " LIKE ('" + likeValue + "')");
+ sql.Where($"{fieldName} LIKE ('{likeValue}')");
return sql;
}
@@ -162,9 +188,7 @@ namespace Umbraco.Extensions
/// A subquery returning the value.
/// The Sql statement.
public static Sql WhereNotIn(this Sql sql, Expression> field, Sql values)
- {
- return sql.WhereIn(field, values, true);
- }
+ => sql.WhereIn(field, values, true);
///
/// Appends multiple OR WHERE IN clauses to the Sql statement.
@@ -258,8 +282,8 @@ namespace Umbraco.Extensions
/// The Sql statement.
public static Sql WhereNull(this Sql sql, Expression> field, string? tableAlias = null, bool not = false)
{
- var column = sql.GetColumns(columnExpressions: new[] { field }, tableAlias: tableAlias, withAlias: false).First();
- return sql.Where("(" + column + " IS " + (not ? "NOT " : string.Empty) + "NULL)");
+ var column = sql.GetColumns(columnExpressions: [field], tableAlias: tableAlias, withAlias: false).First();
+ return sql.Where($"({column} IS {(not ? "NOT " : string.Empty)}NULL)");
}
#endregion
@@ -275,7 +299,7 @@ namespace Umbraco.Extensions
/// The Sql statement.
public static Sql From(this Sql sql, string? alias = null)
{
- Type type = typeof (TDto);
+ Type type = typeof(TDto);
var tableName = type.GetTableName();
var from = sql.SqlContext.SqlSyntax.GetQuotedTableName(tableName);
@@ -738,7 +762,7 @@ namespace Umbraco.Extensions
var text = "COUNT (" + string.Join(", ", columns) + ")";
if (alias != null)
{
- text += " AS " + sql.SqlContext.SqlSyntax.GetQuotedColumnName(alias);
+ text += " AS " + sqlSyntax.GetQuotedColumnName(alias);
}
return sql.Select(text);
@@ -1096,7 +1120,7 @@ namespace Umbraco.Extensions
private SqlRef Select(PropertyInfo? propertyInfo, string? tableAlias, Func, SqlRef>? nested = null)
{
- var referenceName = propertyInfo?.Name ?? typeof (TDto).Name;
+ var referenceName = propertyInfo?.Name ?? typeof(TDto).Name;
if (Prefix != null)
{
referenceName = Prefix + PocoData.Separator + referenceName;
@@ -1163,6 +1187,45 @@ namespace Umbraco.Extensions
return string.Join(", ", sql.GetColumns(columnExpressions: fields, withAlias: false, tableAlias: alias));
}
+ ///
+ /// Adds a SELECT clause to the SQL query based on the specified predicate and optional alias, and prepends an
+ /// opening parenthesis to the query. This is used for selects within "WHERE [column] IN (SELECT ...)" statements.
+ ///
+ /// The modified SQL query with the prepended SELECT clause and opening parenthesis.
+ public static Sql SelectClosure(this Sql sql, Func, SqlConvert> converts)
+ {
+ sql.Append($"(SELECT ");
+
+ var c = new SqlConvert(sql.SqlContext);
+ c = converts(c);
+ var first = true;
+ foreach (string setExpression in c.SetExpressions)
+ {
+ sql.Append($"{(first ? string.Empty : ",")} {setExpression}");
+ first = false;
+ }
+
+ if (!first)
+ {
+ sql.Append(" ");
+ }
+
+ return sql;
+ }
+
+ public class SqlConvert(ISqlContext sqlContext)
+ {
+ public List SetExpressions { get; } = [];
+
+ public SqlConvert ConvertUniqueIdentifierToString(Expression> fieldSelector)
+ {
+ var fieldName = sqlContext.SqlSyntax.GetFieldNameForUpdate(fieldSelector);
+ var convertFieldName = string.Format(sqlContext.SqlSyntax.ConvertUniqueIdentifierToString, fieldName);
+ SetExpressions.Add(convertFieldName);
+ return this;
+ }
+ }
+
#endregion
#region Delete
@@ -1308,7 +1371,7 @@ namespace Umbraco.Extensions
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));
+ PocoData? pd = sql.SqlContext.PocoDataFactory.ForType(typeof(TDto));
var tableName = tableAlias ?? pd.TableInfo.TableName;
var queryColumns = pd.QueryColumns.ToList();
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs
index 0b0a964298..befaa6bc3a 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs
@@ -181,28 +181,36 @@ internal abstract class ContentTypeRepositoryBase : EntityRepositoryBas
ContentTypeDto dto = ContentTypeFactory.BuildContentTypeDto(entity);
// Cannot add a duplicate content type
- var exists = Database.ExecuteScalar(
- @"SELECT COUNT(*) FROM cmsContentType
-INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id
-WHERE cmsContentType." + SqlSyntax.GetQuotedColumnName("alias") + @"= @alias
-AND umbracoNode.nodeObjectType = @objectType",
- new { alias = entity.Alias, objectType = NodeObjectTypeId });
+ Sql sqlDuplicates = Sql()
+ .SelectCount()
+ .From()
+ .InnerJoin().On(left => left.NodeId, right => right.NodeId)
+ .Where(x => x.NodeObjectType == NodeObjectTypeId)
+ .Where(x => x.Alias == entity.Alias);
+ var exists = Database.ExecuteScalar(sqlDuplicates);
if (exists > 0)
{
throw new DuplicateNameException("An item with the alias " + entity.Alias + " already exists");
}
// Logic for setting Path, Level and SortOrder
- NodeDto? parent = Database.First("WHERE id = @ParentId", new { entity.ParentId });
- var level = parent.Level + 1;
- var sortOrder =
- Database.ExecuteScalar(
- "SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType",
- new { entity.ParentId, NodeObjectType = NodeObjectTypeId });
+ Sql sqlParent = Sql()
+ .SelectAll()
+ .From()
+ .Where(x => x.NodeId == entity.ParentId)
+ .SelectTop(1);
+ NodeDto? parent = Database.FirstOrDefault(sqlParent);
+
+ var level = (parent?.Level ?? 0) + 1;
+ Sql sqlSortOrder = Sql()
+ .SelectCount()
+ .From()
+ .Where(x => x.ParentId == entity.ParentId && x.NodeObjectType == NodeObjectTypeId);
+ var sortOrder = Database.ExecuteScalar(sqlSortOrder);
// Create the (base) node data - umbracoNode
NodeDto nodeDto = dto.NodeDto;
- nodeDto.Path = parent.Path;
+ nodeDto.Path = parent?.Path ?? Constants.System.RootString;
nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture));
nodeDto.SortOrder = sortOrder;
var o = Database.IsNew(nodeDto)
@@ -210,7 +218,7 @@ AND umbracoNode.nodeObjectType = @objectType",
: Database.Update(nodeDto);
// Update with new correct path
- nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId);
+ nodeDto.Path = string.Concat(nodeDto.Path, ",", nodeDto.NodeId);
Database.Update(nodeDto);
// Update entity with correct values
@@ -238,10 +246,12 @@ AND umbracoNode.nodeObjectType = @objectType",
else
{
// Fallback for ContentTypes with no identity
- ContentTypeDto? contentTypeDto =
- Database.FirstOrDefault(
- "WHERE alias = @Alias",
- new { composition.Alias });
+ Sql sqlDto = Sql()
+ .SelectAll()
+ .From()
+ .Where(x => x.Alias == composition.Alias)
+ .SelectTop(1);
+ ContentTypeDto? contentTypeDto = Database.FirstOrDefault(sqlDto);
if (contentTypeDto != null)
{
Database.Insert(new ContentType2ContentTypeDto
@@ -254,7 +264,7 @@ AND umbracoNode.nodeObjectType = @objectType",
}
(TEntity Entity, int SortOrder)[] allowedContentTypes = GetAllowedContentTypes(entity);
- if (allowedContentTypes.Any())
+ if (allowedContentTypes.Length > 0)
{
// Insert collection of allowed content types
foreach ((TEntity entity1, int sortOrder1) in allowedContentTypes)
@@ -269,7 +279,8 @@ AND umbracoNode.nodeObjectType = @objectType",
}
// Insert Tabs
- foreach (PropertyGroup propertyGroup in entity.PropertyGroups)
+ PropertyGroupCollection propertyGroups = entity.PropertyGroups;
+ foreach (PropertyGroup propertyGroup in propertyGroups)
{
PropertyTypeGroupDto tabDto = PropertyGroupFactory.BuildGroupDto(propertyGroup, nodeDto.NodeId);
var primaryKey = Convert.ToInt32(Database.Insert(tabDto));
@@ -291,7 +302,8 @@ AND umbracoNode.nodeObjectType = @objectType",
}
// Insert PropertyTypes
- foreach (IPropertyType propertyType in entity.PropertyTypes)
+ IEnumerable propertyTypes = entity.PropertyTypes;
+ foreach (IPropertyType propertyType in propertyTypes)
{
var tabId = propertyType.PropertyGroupId != null ? propertyType.PropertyGroupId.Value : default;
@@ -307,10 +319,17 @@ AND umbracoNode.nodeObjectType = @objectType",
propertyType.Id = typePrimaryKey; // Set Id on new PropertyType
// Update the current PropertyType with correct PropertyEditorAlias and DatabaseType
- DataTypeDto? dataTypeDto =
- Database.FirstOrDefault("WHERE nodeId = @Id", new { Id = propertyTypeDto.DataTypeId });
- propertyType.PropertyEditorAlias = dataTypeDto.EditorAlias;
- propertyType.ValueStorageType = dataTypeDto.DbType.EnumParse(true);
+ Sql sqlDataType = Sql()
+ .SelectAll()
+ .From()
+ .Where(x => x.NodeId == propertyType.DataTypeId)
+ .SelectTop(1);
+ DataTypeDto? dataTypeDto = Database.FirstOrDefault(sqlDataType);
+ if (dataTypeDto is not null)
+ {
+ propertyType.PropertyEditorAlias = dataTypeDto.EditorAlias;
+ propertyType.ValueStorageType = dataTypeDto.DbType.EnumParse(true);
+ }
}
CommonRepository.ClearCache(); // always
@@ -324,13 +343,14 @@ AND umbracoNode.nodeObjectType = @objectType",
ContentTypeDto dto = ContentTypeFactory.BuildContentTypeDto(entity);
// ensure the alias is not used already
- var exists = Database.ExecuteScalar(
- @"SELECT COUNT(*) FROM cmsContentType
-INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id
-WHERE cmsContentType." + SqlSyntax.GetQuotedColumnName("alias") + @"= @alias
-AND umbracoNode.nodeObjectType = @objectType
-AND umbracoNode.id <> @id",
- new { id = dto.NodeId, alias = dto.Alias, objectType = NodeObjectTypeId });
+ Sql sqlContentType1 = Sql()
+ .SelectCount()
+ .From()
+ .InnerJoin().On(left => left.NodeId, right => right.NodeId)
+ .Where(x => x.Alias == dto.Alias)
+ .Where(x => x.NodeObjectType == NodeObjectTypeId && x.NodeId != dto.NodeId);
+ var exists = Database.ExecuteScalar(sqlContentType1);
+
if (exists > 0)
{
throw new DuplicateNameException("An item with the alias " + dto.Alias + " already exists");
@@ -344,12 +364,20 @@ AND umbracoNode.id <> @id",
// we NEED this: updating, so the .PrimaryKey already exists, but the entity does
// not carry it and therefore the dto does not have it yet - must get it from db,
// look up ContentType entry to get PrimaryKey for updating the DTO
- ContentTypeDto? dtoPk = Database.First("WHERE nodeId = @Id", new { entity.Id });
+ Sql sqlContentType2 = Sql()
+ .SelectAll()
+ .From()
+ .Where(x => x.NodeId == dto.NodeId)
+ .SelectTop(1);
+ ContentTypeDto? dtoPk = Database.First(sqlContentType2);
dto.PrimaryKey = dtoPk.PrimaryKey;
Database.Update(dto);
// handle (delete then recreate) compositions
- Database.Delete("WHERE childContentTypeId = @Id", new { entity.Id });
+ Sql sqlContentType2ContentType = Sql()
+ .Delete()
+ .Where(x => x.ChildId == entity.Id);
+ Database.Execute(sqlContentType2ContentType);
foreach (IContentTypeComposition composition in entity.ContentTypeComposition)
{
Database.Insert(new ContentType2ContentTypeDto { ParentId = composition.Id, ChildId = entity.Id });
@@ -364,20 +392,24 @@ AND umbracoNode.id <> @id",
// TODO: Could we do the below with bulk SQL statements instead of looking everything up and then manipulating?
// find Content based on the current ContentType
- Sql sql = Sql()
+ Sql sqlContent = Sql()
.SelectAll()
.From()
.InnerJoin().On(left => left.NodeId, right => right.NodeId)
.Where(x => x.NodeObjectType == Constants.ObjectTypes.Document)
.Where(x => x.ContentTypeId == entity.Id);
- List? contentDtos = Database.Fetch(sql);
+ List? contentDtos = Database.Fetch(sqlContent);
// loop through all tracked keys, which corresponds to the ContentTypes that has been removed from the composition
foreach (var key in entity.RemovedContentTypes)
{
// find PropertyTypes for the removed ContentType
+ Sql sqlPropertyType = Sql()
+ .SelectAll()
+ .From()
+ .Where(x => x.ContentTypeId == key);
List? propertyTypes =
- Database.Fetch("WHERE contentTypeId = @Id", new { Id = key });
+ Database.Fetch(sqlPropertyType);
// loop through the Content that is based on the current ContentType in order to remove the Properties that are
// based on the PropertyTypes that belong to the removed ContentType.
@@ -388,7 +420,7 @@ AND umbracoNode.id <> @id",
{
var nodeId = contentDto.NodeId;
var propertyTypeId = propertyType.Id;
- Sql propertySql = Sql()
+ Sql sqlProperty = Sql()
.Select(x => x.Id)
.From()
.InnerJoin()
@@ -399,16 +431,20 @@ AND umbracoNode.id <> @id",
.Where(x => x.Id == propertyTypeId);
// finally delete the properties that match our criteria for removing a ContentType from the composition
- Database.Delete(new Sql(
- "WHERE id IN (" + propertySql.SQL + ")",
- propertySql.Arguments));
+ Sql sqlPropertydata = Sql()
+ .Delete()
+ .WhereIn(x => x.Id, sqlProperty.Arguments);
+ Database.Execute(sqlPropertydata);
}
}
}
}
// delete the allowed content type entries before re-inserting the collection of allowed content types
- Database.Delete("WHERE Id = @Id", new { entity.Id });
+ Sql sqlAllowedContent = Sql()
+ .Delete()
+ .Where(x => x.Id == entity.Id);
+ Database.Execute(sqlAllowedContent);
(TEntity Entity, int SortOrder)[] allowedContentTypes = GetAllowedContentTypes(entity);
if (allowedContentTypes.Any())
@@ -431,8 +467,11 @@ AND umbracoNode.id <> @id",
if (entity.IsPropertyDirty("NoGroupPropertyTypes") ||
entity.PropertyGroups.Any(x => x.IsPropertyDirty("PropertyTypes")))
{
- List? dbPropertyTypes =
- Database.Fetch("WHERE contentTypeId = @Id", new { entity.Id });
+ Sql sqlPropertyType = Sql()
+ .SelectAll()
+ .From()
+ .Where(x => x.ContentTypeId == entity.Id);
+ List? dbPropertyTypes = Database.Fetch(sqlPropertyType);
IEnumerable dbPropertyTypeIds = dbPropertyTypes.Select(x => x.Id);
IEnumerable entityPropertyTypes = entity.PropertyTypes.Where(x => x.HasIdentity).Select(x => x.Id);
IEnumerable propertyTypeToDeleteIds = dbPropertyTypeIds.Except(entityPropertyTypes);
@@ -465,10 +504,12 @@ AND umbracoNode.id <> @id",
// delete tabs that do not exist anymore
// get the tabs that are currently existing (in the db), get the tabs that we want,
// now, and derive the tabs that we want to delete
- var existingPropertyGroups = Database
- .Fetch("WHERE contentTypeNodeId = @id", new { id = entity.Id })
- .Select(x => x.Id)
- .ToList();
+ Sql sqlPropTypeGrp1 = Sql()
+ .Select(x => x.Id)
+ .From()
+ .Where(x => x.ContentTypeNodeId == entity.Id);
+ List existingPropertyGroups = Database.Fetch(sqlPropTypeGrp1);
+
var newPropertyGroups = entity.PropertyGroups.Select(x => x.Id).ToList();
var groupsToDelete = existingPropertyGroups
.Except(newPropertyGroups)
@@ -481,16 +522,21 @@ AND umbracoNode.id <> @id",
// - move them to 'generic properties' so they remain consistent
// - keep track of them, later on we'll figure out what to do with them
// see http://issues.umbraco.org/issue/U4-8663
- orphanPropertyTypeIds = Database.Fetch(
- "WHERE propertyTypeGroupId IN (@ids)",
- new { ids = groupsToDelete })
- .Select(x => x.Id).ToList();
- Database.Update(
- "SET propertyTypeGroupId = NULL WHERE propertyTypeGroupId IN (@ids)",
- new { ids = groupsToDelete });
+ Sql sqlPropTypeGrp2 = Sql()
+ .Select(x => x.Id)
+ .From()
+ .WhereIn(x => x.PropertyTypeGroupId, groupsToDelete);
+ orphanPropertyTypeIds = Database.Fetch(sqlPropTypeGrp2);
+ Sql sqlPropTypeGrp3 = Sql()
+ .Update(u => u.Set(x => x.PropertyTypeGroupId, null))
+ .WhereIn(x => x.PropertyTypeGroupId, groupsToDelete);
+ Database.Execute(sqlPropTypeGrp3);
// now we can delete the tabs
- Database.Delete("WHERE id IN (@ids)", new { ids = groupsToDelete });
+ Sql sqlPropTypeGrp4 = Sql()
+ .Delete()
+ .WhereIn(x => x.Id, groupsToDelete);
+ Database.Execute(sqlPropTypeGrp4);
}
}
@@ -905,59 +951,59 @@ AND umbracoNode.id <> @id",
// there's 2x tables to update
// clear out the versionCultureVariation table
- Sql sqlSelect = Sql().Select(x => x.Id)
+ Sql sqlSelectContentVersion = Sql().Select(x => x.Id)
.From()
.InnerJoin()
.On(x => x.Id, x => x.VersionId)
.InnerJoin().On(x => x.NodeId, x => x.NodeId)
.Where(x => x.ContentTypeId == contentType.Id)
.Where(x => x.LanguageId == defaultLanguageId);
- Sql sqlDelete = Sql()
+ Sql sqlDeleteContentVersion = Sql()
.Delete()
- .WhereIn(x => x.Id, sqlSelect);
+ .WhereIn(x => x.Id, sqlSelectContentVersion);
- Database.Execute(sqlDelete);
+ Database.Execute(sqlDeleteContentVersion);
// clear out the documentCultureVariation table
- sqlSelect = Sql().Select(x => x.Id)
+ Sql sqlDocumentCulture = Sql().Select(x => x.Id)
.From()
.InnerJoin().On(x => x.NodeId, x => x.NodeId)
.Where(x => x.ContentTypeId == contentType.Id)
.Where(x => x.LanguageId == defaultLanguageId);
- sqlDelete = Sql()
+ Sql sqlDeleteDocumentCulture = Sql()
.Delete()
- .WhereIn(x => x.Id, sqlSelect);
+ .WhereIn(x => x.Id, sqlDocumentCulture);
- Database.Execute(sqlDelete);
+ Database.Execute(sqlDeleteDocumentCulture);
// now we need to insert names into these 2 tables based on the invariant data
// insert rows into the versionCultureVariationDto table based on the data from contentVersionDto for the default lang
var cols = Sql().ColumnsForInsert(x => x.VersionId, x => x.Name,
x => x.UpdateUserId, x => x.UpdateDate, x => x.LanguageId);
- sqlSelect = Sql().Select(x => x.Id, x => x.Text, x => x.UserId, x => x.VersionDate)
+ Sql sqlSelect2 = Sql().Select(x => x.Id, x => x.Text, x => x.UserId, x => x.VersionDate)
.Append($", {defaultLanguageId}") // default language ID
.From()
.InnerJoin().On(x => x.NodeId, x => x.NodeId)
.Where(x => x.ContentTypeId == contentType.Id);
- Sql? sqlInsert = Sql($"INSERT INTO {ContentVersionCultureVariationDto.TableName} ({cols})")
- .Append(sqlSelect);
+ Sql? sqlInsertContentVersion = Sql($"INSERT INTO {SqlSyntax.GetQuotedTableName(ContentVersionCultureVariationDto.TableName)} ({cols})")
+ .Append(sqlSelect2);
- Database.Execute(sqlInsert);
+ Database.Execute(sqlInsertContentVersion);
// insert rows into the documentCultureVariation table
cols = Sql().ColumnsForInsert(x => x.NodeId, x => x.Edited, x => x.Published,
x => x.Name, x => x.Available, x => x.LanguageId);
- sqlSelect = Sql().Select(x => x.NodeId, x => x.Edited, x => x.Published)
+ Sql sqlSelectDocument = Sql().Select(x => x.NodeId, x => x.Edited, x => x.Published)
.AndSelect(x => x.Text)
.Append($", 1, {defaultLanguageId}") // make Available + default language ID
.From()
.InnerJoin().On(x => x.NodeId, x => x.NodeId)
.InnerJoin().On(x => x.NodeId, x => x.NodeId)
.Where(x => x.ContentTypeId == contentType.Id);
- sqlInsert = Sql($"INSERT INTO {DocumentCultureVariationDto.TableName} ({cols})").Append(sqlSelect);
+ Sql sqlInsertDocumentCulture = Sql($"INSERT INTO {SqlSyntax.GetQuotedTableName(DocumentCultureVariationDto.TableName)} ({cols})").Append(sqlSelectDocument);
- Database.Execute(sqlInsert);
+ Database.Execute(sqlInsertDocumentCulture);
}
}
@@ -977,28 +1023,28 @@ AND umbracoNode.id <> @id",
// delete existing relations (for target language)
// do *not* delete existing tags
- Sql sqlSelectTagsToDelete = Sql()
+ Sql sqlSelectTagsToDelete1 = Sql()
.Select(x => x.Id)
.From()
.InnerJoin().On((tag, rel) => tag.Id == rel.TagId);
if (contentTypeIds != null)
{
- sqlSelectTagsToDelete
+ sqlSelectTagsToDelete1
.InnerJoin()
.On((rel, content) => rel.NodeId == content.NodeId)
.WhereIn(x => x.ContentTypeId, contentTypeIds);
}
- sqlSelectTagsToDelete
+ sqlSelectTagsToDelete1
.WhereIn(x => x.PropertyTypeId, propertyTypeIds)
.Where(x => x.LanguageId.SqlNullableEquals(targetLanguageId, -1));
- Sql sqlDeleteRelations = Sql()
+ Sql sqlDeleteRelations1 = Sql()
.Delete()
- .WhereIn(x => x.TagId, sqlSelectTagsToDelete);
+ .WhereIn(x => x.TagId, sqlSelectTagsToDelete1);
- Database.Execute(sqlDeleteRelations);
+ Database.Execute(sqlDeleteRelations1);
// do *not* delete the tags - they could be used by other content types / property types
/*
@@ -1015,12 +1061,12 @@ AND umbracoNode.id <> @id",
// 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";
- Sql sqlSelectTagsToInsert = Sql()
+ Sql sqlSelectTagsToInsert1 = Sql()
.SelectDistinct(x => x.Text, x => x.Group)
.Append(", " + targetLanguageIdS)
.From();
- sqlSelectTagsToInsert
+ sqlSelectTagsToInsert1
.InnerJoin().On((tag, rel) => tag.Id == rel.TagId)
.LeftJoin("xtags")
.On(
@@ -1029,19 +1075,19 @@ AND umbracoNode.id <> @id",
if (contentTypeIds != null)
{
- sqlSelectTagsToInsert
+ sqlSelectTagsToInsert1
.InnerJoin()
.On((rel, content) => rel.NodeId == content.NodeId)
.WhereIn(x => x.ContentTypeId, contentTypeIds);
}
- sqlSelectTagsToInsert
+ sqlSelectTagsToInsert1
.WhereIn(x => x.PropertyTypeId, propertyTypeIds)
.WhereNull(x => x.Id, "xtags") // ie, not exists
.Where(x => x.LanguageId.SqlNullableEquals(sourceLanguageId, -1));
var cols = Sql().ColumnsForInsert(x => x.Text, x => x.Group, x => x.LanguageId);
- Sql