using System.Linq.Expressions;
using NPoco;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Persistence;
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax;
using Umbraco.Cms.Infrastructure.Runtime;
using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.Persistence;
internal static class UmbracoDatabaseExtensions
{
public static UmbracoDatabase AsUmbracoDatabase(this IUmbracoDatabase database)
{
if (database is not UmbracoDatabase asDatabase)
{
throw new Exception("oops: database.");
}
return asDatabase;
}
///
/// Gets a dictionary of key/values directly from the database, no scope, nothing.
///
/// Used by to determine the runtime state.
public static IReadOnlyDictionary? GetFromKeyValueTable(
this IUmbracoDatabase? database,
string keyPrefix)
{
if (database is null)
{
return null;
}
// create the wildcard where clause
ISqlSyntaxProvider sqlSyntax = database.SqlContext.SqlSyntax;
var whereParam = sqlSyntax.GetStringColumnWildcardComparison(
sqlSyntax.GetColumn(database.SqlContext.DatabaseType, KeyValueDto.TableName, "key", null),
0,
TextColumnType.NVarchar);
Sql? sql = database.SqlContext.Sql()
.Select()
.From()
.Where(whereParam, keyPrefix + sqlSyntax.GetWildcardPlaceholder());
return database.Fetch(sql)
.ToDictionary(x => x.Key, x => x.Value);
}
///
/// Returns true if the database contains the specified table
///
///
///
///
public static bool HasTable(this IUmbracoDatabase database, string tableName)
{
try
{
return database.SqlContext.SqlSyntax.GetTablesInSchema(database)
.Any(table => table.InvariantEquals(tableName));
}
catch (Exception)
{
return false; // will occur if the database cannot connect
}
}
///
/// Returns true if the database contains no tables
///
///
///
public static bool IsDatabaseEmpty(this IUmbracoDatabase database)
=> database.SqlContext.SqlSyntax.GetTablesInSchema(database).Any() == false;
public static long Count(this IUmbracoDatabase database, Sql sql)
{
// We need to copy the sql into a new object, to avoid this method from changing the sql.
var query = new Sql().Select("COUNT(*)").From().Append("(").Append(new Sql(sql.SQL, sql.Arguments)).Append(") as count_query");
return database.ExecuteScalar(query);
}
public static async Task CountAsync(this IUmbracoDatabase database, Sql sql)
{
// We need to copy the sql into a new object, to avoid this method from changing the sql.
Sql query = new Sql().Select("COUNT(*)").From().Append("(").Append(new Sql(sql.SQL, sql.Arguments)).Append(") as count_query");
return await database.ExecuteScalarAsync(query);
}
public static async Task> PagedAsync(
this IUmbracoDatabase database,
Sql sql,
int skip,
int take,
Action> sortingAction,
Func mapper)
{
ArgumentOutOfRangeException.ThrowIfLessThan(skip, 0, nameof(skip));
ArgumentOutOfRangeException.ThrowIfLessThan(take, 0, nameof(take));
var count = await database.CountAsync(sql);
if (take == 0 || skip >= count)
{
return new PagedModel
{
Total = count,
Items = [],
};
}
sortingAction(sql);
List results = await database.SkipTakeAsync(
skip,
take,
sql);
return new PagedModel
{
Total = count,
Items = results.Select(mapper),
};
}
}