U4-6003 List View - Order By Custom Property Fix

Original work done on https://github.com/umbraco/Umbraco-CMS/pull/711 but ported to the latest version

Content below for reference
With the current implementation of the list view you can only sort by system columns (Name, SortOrder etc.) and not custom columns you have added to your document types. This PR allows that.

The crux of it is a sub-query added to the ORDER BY clause when we are ordering by a custom field. This looks up the field's value from the most recent content version.

Provided here and not in the previous pull request is:

MySQL support
Have done some performance testing. On a local laptop with 1000 nodes in a list view, it's sorting in around 220-250ms. It's a little slower that sorting on native properties like node name, but still perfectly usable - there's no significant delay you see in use.
Please note also:

GetPagedResultsByQuery() in VersionableRepositoryBase was previously doing an ORDER BY in SQL and then repeating this via LINQ to Objects. I couldn't see that this second ordering was necessary so removed it, but wanted to flag here in case I've missed something around why this was necessary.
The PR also includes small amends to fix or hide sorting on a couple of the default columns for the member amd media list views.
This commit is contained in:
André Ferreira
2016-02-26 14:30:32 +00:00
parent ac2ebc4071
commit bd2a40d214
31 changed files with 2526 additions and 2457 deletions

View File

@@ -241,8 +241,8 @@ namespace Umbraco.Core.Persistence.Repositories
// see: http://issues.umbraco.org/issue/U4-6322 & http://issues.umbraco.org/issue/U4-5982
var descendants = GetPagedResultsByQuery<DocumentDto, Content>(query, pageIndex, pageSize, out total,
new Tuple<string, string>("cmsDocument", "nodeId"),
ProcessQuery, "Path", Direction.Ascending);
ProcessQuery, "Path", Direction.Ascending, orderBySystemField: true);
var xmlItems = (from descendant in descendants
let xml = serializer(descendant)
select new ContentXmlDto { NodeId = descendant.Id, Xml = xml.ToDataString() }).ToArray();
@@ -766,10 +766,11 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IContent> GetPagedResultsByQuery(IQuery<IContent> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "")
{
//NOTE: This uses the GetBaseQuery method but that does not take into account the required 'newest' field which is
@@ -788,7 +789,7 @@ namespace Umbraco.Core.Persistence.Repositories
return GetPagedResultsByQuery<DocumentDto, Content>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsDocument", "nodeId"),
ProcessQuery, orderBy, orderDirection,
ProcessQuery, orderBy, orderDirection, orderBySystemField,
filterCallback);
}

View File

@@ -84,9 +84,10 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
IEnumerable<IContent> GetPagedResultsByQuery(IQuery<IContent> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "");
}
}

View File

@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
public interface IMediaRepository : IRepositoryVersionable<int, IMedia>, IRecycleBinRepository<IMedia>, IDeleteMediaFilesRepository
{
/// <summary>
/// Used to add/update published xml for the media item
/// </summary>
@@ -33,9 +33,10 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
IEnumerable<IMedia> GetPagedResultsByQuery(IQuery<IMedia> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "");
}
}

View File

@@ -44,16 +44,17 @@ namespace Umbraco.Core.Persistence.Repositories
/// <summary>
/// Gets paged member results
/// </summary>
/// <param name="query"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <param name="query">The query.</param>
/// <param name="pageIndex">Index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
/// <param name="totalRecords">The total records.</param>
/// <param name="orderBy">The order by column</param>
/// <param name="orderDirection">The order direction.</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search query</param>
/// <returns></returns>
IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "");
//IEnumerable<IMember> GetPagedResultsByQuery<TDto>(
// Sql sql, int pageIndex, int pageSize, out int totalRecords,

View File

@@ -232,7 +232,7 @@ namespace Umbraco.Core.Persistence.Repositories
var processed = 0;
do
{
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending);
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending, orderBySystemField: true);
var xmlItems = (from descendant in descendants
let xml = serializer(descendant)
@@ -442,10 +442,11 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetPagedResultsByQuery(IQuery<IMedia> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "")
{
var args = new List<object>();
var sbWhere = new StringBuilder();
@@ -459,7 +460,7 @@ namespace Umbraco.Core.Persistence.Repositories
return GetPagedResultsByQuery<ContentVersionDto, Models.Media>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsContentVersion", "contentId"),
ProcessQuery, orderBy, orderDirection,
ProcessQuery, orderBy, orderDirection, orderBySystemField,
filterCallback);
}
@@ -468,7 +469,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
//NOTE: This doesn't allow properties to be part of the query
var dtos = Database.Fetch<ContentVersionDto, ContentDto, NodeDto>(sql);
var ids = dtos.Select(x => x.ContentDto.ContentTypeId).ToArray();
//content types

View File

@@ -74,7 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories
}
return ProcessQuery(sql);
}
protected override IEnumerable<IMember> PerformGetByQuery(IQuery<IMember> query)
@@ -95,7 +95,7 @@ namespace Umbraco.Core.Persistence.Repositories
baseQuery.Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments))
.OrderBy<NodeDto>(x => x.SortOrder);
return ProcessQuery(baseQuery);
return ProcessQuery(baseQuery);
}
else
{
@@ -103,7 +103,7 @@ namespace Umbraco.Core.Persistence.Repositories
var sql = translator.Translate()
.OrderBy<NodeDto>(x => x.SortOrder);
return ProcessQuery(sql);
return ProcessQuery(sql);
}
}
@@ -118,7 +118,7 @@ namespace Umbraco.Core.Persistence.Repositories
sql.Select(isCount ? "COUNT(*)" : "*")
.From<MemberDto>()
.InnerJoin<ContentVersionDto>()
.On<ContentVersionDto, MemberDto>(left => left.NodeId, right => right.NodeId)
.On<ContentVersionDto, MemberDto>(left => left.NodeId, right => right.NodeId)
.InnerJoin<ContentDto>()
.On<ContentVersionDto, ContentDto>(left => left.NodeId, right => right.NodeId)
//We're joining the type so we can do a query against the member type - not sure if this adds much overhead or not?
@@ -269,7 +269,7 @@ namespace Umbraco.Core.Persistence.Repositories
//Ensure that strings don't contain characters that are invalid in XML
entity.SanitizeEntityPropertiesForXmlStorage();
var dirtyEntity = (ICanBeDirty) entity;
var dirtyEntity = (ICanBeDirty)entity;
//Look up parent to get and set the correct Path and update SortOrder if ParentId has changed
if (dirtyEntity.IsPropertyDirty("ParentId"))
@@ -308,9 +308,9 @@ namespace Umbraco.Core.Persistence.Repositories
//Updates the current version - cmsContentVersion
//Assumes a Version guid exists and Version date (modified date) has been set/updated
Database.Update(dto.ContentVersionDto);
//Updates the cmsMember entry if it has changed
//NOTE: these cols are the REAL column names in the db
var changedCols = new List<string>();
@@ -330,13 +330,13 @@ namespace Umbraco.Core.Persistence.Repositories
//only update the changed cols
if (changedCols.Count > 0)
{
Database.Update(dto, changedCols);
Database.Update(dto, changedCols);
}
//TODO ContentType for the Member entity
//Create the PropertyData for this version - cmsPropertyData
var propertyFactory = new PropertyFactory(entity.ContentType.CompositionPropertyTypes.ToArray(), entity.Version, entity.Id);
var propertyFactory = new PropertyFactory(entity.ContentType.CompositionPropertyTypes.ToArray(), entity.Version, entity.Id);
var keyDictionary = new Dictionary<int, int>();
//Add Properties
@@ -447,7 +447,7 @@ namespace Umbraco.Core.Persistence.Repositories
var processed = 0;
do
{
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending);
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending, orderBySystemField: true);
var xmlItems = (from descendant in descendants
let xml = serializer(descendant)
@@ -559,7 +559,7 @@ namespace Umbraco.Core.Persistence.Repositories
var grpQry = new Query<IMemberGroup>().Where(group => group.Name.Equals(groupName));
var memberGroup = _memberGroupRepository.GetByQuery(grpQry).FirstOrDefault();
if (memberGroup == null) return Enumerable.Empty<IMember>();
var subQuery = new Sql().Select("Member").From<Member2MemberGroupDto>().Where<Member2MemberGroupDto>(dto => dto.MemberGroup == memberGroup.Id);
var sql = GetBaseQuery(false)
@@ -568,7 +568,7 @@ namespace Umbraco.Core.Persistence.Repositories
.Append(new Sql("WHERE umbracoNode.id IN (" + subQuery.SQL + ")", subQuery.Arguments))
.OrderByDescending<ContentVersionDto>(x => x.VersionDate)
.OrderBy<NodeDto>(x => x.SortOrder);
return ProcessQuery(sql);
}
@@ -593,7 +593,7 @@ namespace Umbraco.Core.Persistence.Repositories
//get the COUNT base query
var fullSql = GetBaseQuery(true)
.Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments));
return Database.ExecuteScalar<int>(fullSql);
}
@@ -603,18 +603,19 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="query">
/// The where clause, if this is null all records are queried
/// </param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <param name="pageIndex">Index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
/// <param name="totalRecords">The total records.</param>
/// <param name="orderBy">The order by column</param>
/// <param name="orderDirection">The order direction.</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search query</param>
/// <returns></returns>
/// <remarks>
/// The query supplied will ONLY work with data specifically on the cmsMember table because we are using PetaPoco paging (SQL paging)
/// </remarks>
public IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "")
{
var args = new List<object>();
var sbWhere = new StringBuilder();
@@ -625,14 +626,14 @@ namespace Umbraco.Core.Persistence.Repositories
"OR (cmsMember.LoginName LIKE @0" + args.Count + "))");
args.Add("%" + filter + "%");
filterCallback = () => new Tuple<string, object[]>(sbWhere.ToString().Trim(), args.ToArray());
}
}
return GetPagedResultsByQuery<MemberDto, Member>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsMember", "nodeId"),
ProcessQuery, orderBy, orderDirection,
ProcessQuery, orderBy, orderDirection, orderBySystemField,
filterCallback);
}
public void AddOrUpdateContentXml(IMember content, Func<IMember, XElement> xml)
{
_contentXmlRepository.AddOrUpdate(new ContentXmlEntity<IMember>(content, xml));
@@ -682,7 +683,7 @@ namespace Umbraco.Core.Persistence.Repositories
var dtosWithContentTypes = dtos
//This select into and null check are required because we don't have a foreign damn key on the contentType column
// http://issues.umbraco.org/issue/U4-5503
.Select(x => new {dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId)})
.Select(x => new { dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId) })
.Where(x => x.contentType != null)
.ToArray();
@@ -694,12 +695,12 @@ namespace Umbraco.Core.Persistence.Repositories
d.dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
d.contentType));
var propertyData = GetPropertyCollection(sql, docDefs);
var propertyData = GetPropertyCollection(sql, docDefs);
return dtosWithContentTypes.Select(d => CreateMemberFromDto(
d.dto,
contentTypes.First(ct => ct.Id == d.dto.ContentVersionDto.ContentDto.ContentTypeId),
propertyData[d.dto.NodeId]));
propertyData[d.dto.NodeId]));
}
/// <summary>

View File

@@ -25,6 +25,7 @@ using Umbraco.Core.IO;
namespace Umbraco.Core.Persistence.Repositories
{
using SqlSyntax;
internal abstract class VersionableRepositoryBase<TId, TEntity> : PetaPocoRepositoryBase<TId, TEntity>
where TEntity : class, IAggregateRoot
{
@@ -61,11 +62,11 @@ namespace Umbraco.Core.Persistence.Repositories
public virtual void DeleteVersion(Guid versionId)
{
var dto = Database.FirstOrDefault<ContentVersionDto>("WHERE versionId = @VersionId", new { VersionId = versionId });
if(dto == null) return;
if (dto == null) return;
//Ensure that the lastest version is not deleted
var latestVersionDto = Database.FirstOrDefault<ContentVersionDto>("WHERE ContentId = @Id ORDER BY VersionDate DESC", new { Id = dto.NodeId });
if(latestVersionDto.VersionId == dto.VersionId)
if (latestVersionDto.VersionId == dto.VersionId)
return;
using (var transaction = Database.GetTransaction())
@@ -83,7 +84,7 @@ namespace Umbraco.Core.Persistence.Repositories
var list =
Database.Fetch<ContentVersionDto>(
"WHERE versionId <> @VersionId AND (ContentId = @Id AND VersionDate < @VersionDate)",
new {VersionId = latestVersionDto.VersionId, Id = id, VersionDate = versionDate});
new { VersionId = latestVersionDto.VersionId, Id = id, VersionDate = versionDate });
if (list.Any() == false) return;
using (var transaction = Database.GetTransaction())
@@ -244,23 +245,57 @@ namespace Umbraco.Core.Persistence.Repositories
return filteredSql;
}
private Sql GetSortedSqlForPagedResults(Sql sql, Direction orderDirection, string orderBy)
private Sql GetSortedSqlForPagedResults(Sql sql, Direction orderDirection, string orderBy, bool orderBySystemField)
{
//copy to var so that the original isn't changed
var sortedSql = new Sql(sql.SQL, sql.Arguments);
// Apply order according to parameters
if (string.IsNullOrEmpty(orderBy) == false)
if (orderBySystemField)
{
var orderByParams = new[] { GetDatabaseFieldNameForOrderBy(orderBy) };
if (orderDirection == Direction.Ascending)
// Apply order according to parameters
if (string.IsNullOrEmpty(orderBy) == false)
{
sortedSql.OrderBy(orderByParams);
var orderByParams = new[] { GetDatabaseFieldNameForOrderBy(orderBy) };
if (orderDirection == Direction.Ascending)
{
sortedSql.OrderBy(orderByParams);
}
else
{
sortedSql.OrderByDescending(orderByParams);
}
}
else
}
else
{
// Sorting by a custom field, so set-up sub-query for ORDER BY clause to pull through valie
// from most recent content version for the given order by field
var sortedInt = string.Format(SqlSyntaxContext.SqlSyntaxProvider.ConvertIntegerToOrderableString, "dataInt");
var sortedDate = string.Format(SqlSyntaxContext.SqlSyntaxProvider.ConvertDateToOrderableString, "dataDate");
var sortedString = string.Format(SqlSyntaxContext.SqlSyntaxProvider.IsNull, "dataNvarchar", "''");
var orderBySql = string.Format(@"ORDER BY (
SELECT CASE
WHEN dataInt Is Not Null THEN {0}
WHEN dataDate Is Not Null THEN {1}
ELSE {2}
END
FROM cmsContent c
INNER JOIN cmsContentVersion cv ON cv.ContentId = c.nodeId AND VersionDate = (
SELECT Max(VersionDate)
FROM cmsContentVersion
WHERE ContentId = c.nodeId
)
INNER JOIN cmsPropertyData cpd ON cpd.contentNodeId = c.nodeId
AND cpd.versionId = cv.VersionId
INNER JOIN cmsPropertyType cpt ON cpt.Id = cpd.propertytypeId
WHERE c.nodeId = umbracoNode.Id and cpt.Alias = @0)", sortedInt, sortedDate, sortedString);
sortedSql.Append(orderBySql, orderBy);
if (orderDirection == Direction.Descending)
{
sortedSql.OrderByDescending(orderByParams);
sortedSql.Append(" DESC");
}
return sortedSql;
}
return sortedSql;
}
@@ -279,13 +314,15 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="processQuery">A callback to process the query result</param>
/// <param name="orderBy">The order by column</param>
/// <param name="orderDirection">The order direction.</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">orderBy</exception>
protected IEnumerable<TEntity> GetPagedResultsByQuery<TDto, TContentBase>(IQuery<TEntity> query, long pageIndex, int pageSize, out long totalRecords,
Tuple<string, string> nodeIdSelect,
Func<Sql, IEnumerable<TEntity>> processQuery,
string orderBy,
string orderBy,
Direction orderDirection,
bool orderBySystemField,
Func<Tuple<string, object[]>> defaultFilter = null)
where TContentBase : class, IAggregateRoot, TEntity
{
@@ -297,18 +334,18 @@ namespace Umbraco.Core.Persistence.Repositories
if (query == null) query = new Query<TEntity>();
var translator = new SqlTranslator<TEntity>(sqlBase, query);
var sqlQuery = translator.Translate();
// Note we can't do multi-page for several DTOs like we can multi-fetch and are doing in PerformGetByQuery,
// but actually given we are doing a Get on each one (again as in PerformGetByQuery), we only need the node Id.
// So we'll modify the SQL.
var sqlNodeIds = new Sql(
sqlQuery.SQL.Replace("SELECT *", string.Format("SELECT {0}.{1}",nodeIdSelect.Item1, nodeIdSelect.Item2)),
sqlQuery.SQL.Replace("SELECT *", string.Format("SELECT {0}.{1}", nodeIdSelect.Item1, nodeIdSelect.Item2)),
sqlQuery.Arguments);
//get sorted and filtered sql
var sqlNodeIdsWithSort = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(sqlNodeIds, defaultFilter),
orderDirection, orderBy);
orderDirection, orderBy, orderBySystemField);
// Get page of results and total count
IEnumerable<TEntity> result;
@@ -324,7 +361,7 @@ namespace Umbraco.Core.Persistence.Repositories
var args = sqlNodeIdsWithSort.Arguments;
string sqlStringCount, sqlStringPage;
Database.BuildPageQueries<TDto>(pageIndex * pageSize, pageSize, sqlNodeIdsWithSort.SQL, ref args, out sqlStringCount, out sqlStringPage);
//if this is for sql server, the sqlPage will start with a SELECT * but we don't want that, we only want to return the nodeId
sqlStringPage = sqlStringPage
.Replace("SELECT *",
@@ -333,7 +370,7 @@ namespace Umbraco.Core.Persistence.Repositories
"SELECT " + nodeIdSelect.Item2);
//We need to make this an inner join on the paged query
var splitQuery = sqlQuery.SQL.Split(new[] {"WHERE "}, StringSplitOptions.None);
var splitQuery = sqlQuery.SQL.Split(new[] { "WHERE " }, StringSplitOptions.None);
var withInnerJoinSql = new Sql(splitQuery[0])
.Append("INNER JOIN (")
//join the paged query with the paged query arguments
@@ -345,23 +382,9 @@ namespace Umbraco.Core.Persistence.Repositories
//get sorted and filtered sql
var fullQuery = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(withInnerJoinSql, defaultFilter),
orderDirection, orderBy);
var content = processQuery(fullQuery)
.Cast<TContentBase>()
.AsQueryable();
// Now we need to ensure this result is also ordered by the same order by clause
var orderByProperty = GetEntityPropertyNameForOrderBy(orderBy);
if (orderDirection == Direction.Ascending)
{
result = content.OrderBy(orderByProperty);
}
else
{
result = content.OrderByDescending(orderByProperty);
}
GetFilteredSqlForPagedResults(withInnerJoinSql, defaultFilter),
orderDirection, orderBy, orderBySystemField);
return processQuery(fullQuery);
}
else
{
@@ -394,9 +417,9 @@ INNER JOIN
(" + string.Format(parsedOriginalSql, "cmsContent.nodeId, cmsContentVersion.VersionId") + @") as docData
ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.contentNodeId = docData.nodeId
LEFT OUTER JOIN cmsDataTypePreValues
ON cmsPropertyType.dataTypeId = cmsDataTypePreValues.datatypeNodeId", docSql.Arguments);
ON cmsPropertyType.dataTypeId = cmsDataTypePreValues.datatypeNodeId", docSql.Arguments);
var allPropertyData = Database.Fetch<PropertyDataDto>(propSql);
var allPropertyData = Database.Fetch<PropertyDataDto>(propSql);
//This is a lazy access call to get all prevalue data for the data types that make up all of these properties which we use
// below if any property requires tag support
@@ -414,7 +437,7 @@ WHERE EXISTS(
ON cmsPropertyType.contentTypeId = docData.contentType
WHERE a.id = b.id)", docSql.Arguments);
return Database.Fetch<DataTypePreValueDto>(preValsSql);
return Database.Fetch<DataTypePreValueDto>(preValsSql);
});
var result = new Dictionary<int, PropertyCollection>();
@@ -432,8 +455,8 @@ WHERE EXISTS(
var propertyDataDtos = allPropertyData.Where(x => x.NodeId == def.Id).Distinct();
var propertyFactory = new PropertyFactory(compositionProperties, def.Version, def.Id, def.CreateDate, def.VersionDate);
var properties = propertyFactory.BuildEntity(propertyDataDtos.ToArray()).ToArray();
var properties = propertyFactory.BuildEntity(propertyDataDtos.ToArray()).ToArray();
var newProperties = properties.Where(x => x.HasIdentity == false && x.PropertyType.HasIdentity);
foreach (var property in newProperties)
@@ -481,7 +504,7 @@ WHERE EXISTS(
Logger.Warn<VersionableRepositoryBase<TId, TEntity>>("The query returned multiple property sets for document definition " + def.Id + ", " + def.Composition.Name);
}
result[def.Id] = new PropertyCollection(properties);
}
}
}
return result;
@@ -521,6 +544,9 @@ WHERE EXISTS(
case "OWNER":
//TODO: This isn't going to work very nicely because it's going to order by ID, not by letter
return "umbracoNode.nodeUser";
// Members only
case "USERNAME":
return "cmsMember.LoginName";
default:
//ensure invalid SQL cannot be submitted
return Regex.Replace(orderBy, @"[^\w\.,`\[\]@-]", "");

View File

@@ -70,6 +70,10 @@ namespace Umbraco.Core.Persistence.SqlSyntax
bool SupportsIdentityInsert();
bool? SupportsCaseInsensitiveQueries(Database db);
string IsNull { get; }
string ConvertIntegerToOrderableString { get; }
string ConvertDateToOrderableString { get; }
IEnumerable<string> GetTablesInSchema(Database db);
IEnumerable<ColumnInfo> GetColumnsInSchema(Database db);
IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db);

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public MySqlSyntaxProvider(ILogger logger)
{
_logger = logger;
AutoIncrementDefinition = "AUTO_INCREMENT";
IntColumnDefinition = "int(11)";
BoolColumnDefinition = "tinyint(1)";
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
TimeColumnDefinition = "time";
DecimalColumnDefinition = "decimal(38,6)";
GuidColumnDefinition = "char(36)";
DefaultValueFormat = "DEFAULT {0}";
InitColumnTypeMap();
@@ -326,13 +326,13 @@ ORDER BY TABLE_NAME, INDEX_NAME",
{
case SystemMethods.NewGuid:
return null; // NOT SUPPORTED!
//return "NEWID()";
//return "NEWID()";
case SystemMethods.CurrentDateTime:
return "CURRENT_TIMESTAMP";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
}
return null;
@@ -360,6 +360,9 @@ ORDER BY TABLE_NAME, INDEX_NAME",
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
public override string RenameColumn { get { return "ALTER TABLE {0} CHANGE {1} {2}"; } }
public override string IsNull { get { return "IFNULL({0},{1})"; } }
public override string ConvertIntegerToOrderableString { get { return "LPAD({0}, 8, '0')"; } }
public override string ConvertDateToOrderableString { get { return "DATE_FORMAT({0}, '%Y%m%d')"; } }
public override bool? SupportsCaseInsensitiveQueries(Database db)
{

View File

@@ -322,7 +322,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
GetQuotedColumnName(foreignKey.ForeignColumns.First()),
GetQuotedTableName(foreignKey.PrimaryTable),
GetQuotedColumnName(foreignKey.PrimaryColumns.First()),
FormatCascade("DELETE", foreignKey.OnDelete),
FormatCascade("DELETE", foreignKey.OnDelete),
FormatCascade("UPDATE", foreignKey.OnUpdate));
}
@@ -331,7 +331,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
var sb = new StringBuilder();
foreach (var column in columns)
{
sb.Append(Format(column) +",\n");
sb.Append(Format(column) + ",\n");
}
return sb.ToString().TrimEnd(",\n");
}
@@ -431,11 +431,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return GetSpecialDbType(column.DbType);
}
Type type = column.Type.HasValue
Type type = column.Type.HasValue
? DbTypeMap.ColumnDbTypeMap.First(x => x.Value == column.Type.Value).Key
: column.PropertyType;
if (type == typeof (string))
if (type == typeof(string))
{
var valueOrDefault = column.Size != default(int) ? column.Size : DefaultStringLength;
return string.Format(StringLengthColumnDefinitionFormat, valueOrDefault);
@@ -536,5 +536,9 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } }
public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } }
public virtual string CreateForeignKeyConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}){5}{6}"; } }
public virtual string IsNull { get { return "ISNULL({0},{1})"; } }
public virtual string ConvertIntegerToOrderableString { get { return "RIGHT('00000000' + CAST({0} AS varchar(8)),8)"; } }
public virtual string ConvertDateToOrderableString { get { return "CONVERT(varchar, {0}, 102)"; } }
}
}