From 3dcc7ead1ce3a08261480bb87d5f9e376d2788c9 Mon Sep 17 00:00:00 2001 From: jibedoubleve Date: Wed, 7 Jun 2023 16:23:21 +0200 Subject: [PATCH] (#77): Manage synonyms for alias --- src/Lanceur.Core/Models/AliasQueryResult.cs | 43 +-- .../Models/ExistingNameResponse.cs | 33 ++ src/Lanceur.Core/Models/QueryResult.cs | 22 +- .../Repositories/IDbRepository.cs | 10 +- .../DbActions/AliasDbAction.cs | 200 ++++++------ src/Lanceur.Infra.SQLite/SQLiteRepository.cs | 91 +++--- .../BusinessLogic/AliasManagementShould.cs | 306 ++++++++---------- src/Lanceur.Tests/Models/QueryResultShould.cs | 33 +- src/Lanceur/Lanceur.csproj | 2 + src/Lanceur/SQL/script-0.11.sql | 7 + src/Lanceur/Views/KeywordsView.xaml | 13 +- src/Lanceur/Views/KeywordsView.xaml.cs | 14 +- src/Lanceur/Views/KeywordsViewModel.cs | 61 ++-- 13 files changed, 383 insertions(+), 452 deletions(-) create mode 100644 src/Lanceur.Core/Models/ExistingNameResponse.cs create mode 100644 src/Lanceur/SQL/script-0.11.sql diff --git a/src/Lanceur.Core/Models/AliasQueryResult.cs b/src/Lanceur.Core/Models/AliasQueryResult.cs index 43c25ceb..1f48a508 100644 --- a/src/Lanceur.Core/Models/AliasQueryResult.cs +++ b/src/Lanceur.Core/Models/AliasQueryResult.cs @@ -7,28 +7,19 @@ public static class AliasQueryResultMixin { #region Methods - public static AliasQueryResult Duplicate(this AliasQueryResult @this) + + public static string[] GetNames(this AliasQueryResult @this) { - return new AliasQueryResult - { - Parameters = @this.Parameters, - Count = @this.Count, - FileName = @this.FileName, - Icon = @this.Icon, - Notes = @this.Notes, - Name = $"Duplicate of {@this.Name}", - RunAs = @this.RunAs, - WorkingDirectory = @this.WorkingDirectory, - StartMode = @this.StartMode, - Query = @this.Query, - // In case it's already a duplicate of a duplicate, - // go recursively all the way down to the original - DuplicateOf = @this.DuplicateOf ?? @this.Id - }; + if (@this is null) { return Array.Empty(); } + if (@this.Synonyms is null) { return Array.Empty(); } + + return + @this.Synonyms + .Split(",") + .Select(n => n.Trim()) + .ToArray(); } - public static bool HasChangedName(this AliasQueryResult @this) => @this.Name?.ToLower() != @this.OldName.ToLower(); - #endregion Methods } @@ -54,12 +45,6 @@ public override string Description set => Notes = value; } - /// - /// If this is a ducplicate from another - /// alias, this contains its ID. Otherwise contains NULL - /// - public long? DuplicateOf { get; set; } - public string FileName { get => _fileName; @@ -82,13 +67,19 @@ public override bool IsElevated public StartMode StartMode { get; set; } = StartMode.Default; + /// + /// Get or set a string representing all the name this alias has. + /// It should be a coma separated list of names. + /// + public string Synonyms { get; set; } + public string WorkingDirectory { get; set; } #endregion Properties #region Methods - public static AliasQueryResult FromName(string aliasName) => new AliasQueryResult() { Name = aliasName }; + public static AliasQueryResult FromName(string aliasName) => new AliasQueryResult() { Name = aliasName, Synonyms = aliasName }; #endregion Methods } diff --git a/src/Lanceur.Core/Models/ExistingNameResponse.cs b/src/Lanceur.Core/Models/ExistingNameResponse.cs new file mode 100644 index 00000000..cd0c07e5 --- /dev/null +++ b/src/Lanceur.Core/Models/ExistingNameResponse.cs @@ -0,0 +1,33 @@ +namespace Lanceur.Core.Models +{ + /// + /// Represents the response when checks whether the names specified is alias names + /// + public record ExistingNameResponse + { + #region Constructors + + public ExistingNameResponse(string[] existingNames) + { + ExistingNames = existingNames is null + ? Array.Empty() + : existingNames; + } + + #endregion Constructors + + #region Properties + + /// + /// List of existing names. Empty if no names exists + /// + public string[] ExistingNames { get; } + + /// + /// True if at least one of the names to check already exist; otherwise False + /// + public bool Exists => ExistingNames?.Any() ?? false; + + #endregion Properties + } +} \ No newline at end of file diff --git a/src/Lanceur.Core/Models/QueryResult.cs b/src/Lanceur.Core/Models/QueryResult.cs index 6bccd111..6cf53ebf 100644 --- a/src/Lanceur.Core/Models/QueryResult.cs +++ b/src/Lanceur.Core/Models/QueryResult.cs @@ -16,9 +16,6 @@ public abstract class QueryResult : ObservableModel { #region Fields - private string _name = string.Empty; - private string _oldName; - private object _thumbnail; #endregion Fields @@ -30,6 +27,8 @@ public abstract class QueryResult : ObservableModel public int Count { get; set; } = 0; public virtual string Description { get; set; } + public string Name { get; set; } + /// /// Fall back for . This property is expected to /// contain information to display an icon (or whatever) in the UI @@ -48,21 +47,6 @@ public abstract class QueryResult : ObservableModel /// public virtual bool IsResult => true; - public string Name - { - get => _name; - set - { - // First time you set the name of the QueryResult, it'll save - // the value. Now, OldName will have the value of the first time - // it was set. - if (value != null && _oldName == null) { _oldName = value.ToLower(); } - Set(ref _name, value); - } - } - - public string OldName => _oldName; - public Cmdline Query { get; set; } = Cmdline.Empty; /// @@ -82,7 +66,7 @@ public object Thumbnail #region Methods - public override int GetHashCode() => (Count, Description, Icon, Id, IsResult, Name, OldName, Query, Thumbnail).GetHashCode(); + public override int GetHashCode() => (Count, Description, Icon, Id, IsResult, Name, Query, Thumbnail).GetHashCode(); public virtual string ToQuery() => $"{Name}"; diff --git a/src/Lanceur.Core/Repositories/IDbRepository.cs b/src/Lanceur.Core/Repositories/IDbRepository.cs index 5a3c858b..6ecd7b03 100644 --- a/src/Lanceur.Core/Repositories/IDbRepository.cs +++ b/src/Lanceur.Core/Repositories/IDbRepository.cs @@ -14,6 +14,14 @@ public interface IDbRepository { #region Methods + /// + /// Checks whether the specified names exists in the database for the specified session + /// + /// + /// + /// + public ExistingNameResponse CheckNamesExist(string[] names, long? idSession = null); + /// /// Get all the aliases /// @@ -66,7 +74,7 @@ public interface IDbRepository IEnumerable> GetUsage(Per per, long? idSession = null); /// - /// Hydrate the macro with its id and count. This method will try to find the + /// Hydrate the macro with its id and count. This method will try to find the /// macro by using its name that should be something like '@it_s_name@' /// /// Macro to hydrate diff --git a/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs b/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs index 48f5ddb9..d546923c 100644 --- a/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs +++ b/src/Lanceur.Infra.SQLite/DbActions/AliasDbAction.cs @@ -1,8 +1,6 @@ using Dapper; -using Lanceur.Core.Managers; using Lanceur.Core.Models; using Lanceur.Core.Services; -using Lanceur.Core.Utils; namespace Lanceur.Infra.SQLite.DbActions { @@ -27,6 +25,30 @@ public AliasDbAction(SQLiteConnectionScope db, IAppLoggerFactory logFactory) #region Methods + internal IEnumerable RefreshUsage(IEnumerable results) + { + var ids = (from r in results + where r.Id != 0 + select r); + var sql = @" + select + id_alias as id, + count + from + stat_usage_per_app_v + where id_alias in @ids;"; + + var dbResults = _db.Connection.Query(sql, new { ids = results.Select(x => x.Id).ToArray() }); + + foreach (var result in results) + { + result.Count = (from item in dbResults + where item.Id == result.Id + select item.Count).SingleOrDefault(); + } + return results; + } + public bool CheckNameExists(AliasQueryResult alias, long idSession) { var sql = @" @@ -46,6 +68,23 @@ alias_name an return count > 0; } + public ExistingNameResponse CheckNameExists(string[] names, long idSession) + { + var sql = @" + select an.name + from + alias_name an + inner join alias a on a.id = an.id_alias + where an.name in @names + and a.id_session = @idSession"; + + var result = _db.Connection + .Query(sql, new { names, idSession }) + .ToArray(); + + return new(result); + } + public long Create(ref AliasQueryResult alias, long idSession) { //Create the alias @@ -83,9 +122,14 @@ insert into alias ( alias.WorkingDirectory }); - alias.Id = id; + // Create synonyms + sql = @"insert into alias_name (id_alias, name) values (@id, @name)"; + foreach (var name in alias.GetNames()) + { + _db.Connection.ExecuteScalar(sql, new { id, name }); + } - Duplicate(alias); + alias.Id = id; // Return either the id of the created Alias or // return the id of the just updated allias (which @@ -95,22 +139,6 @@ insert into alias ( public void Dispose() => _db.Dispose(); - public void Duplicate(AliasQueryResult alias) - { - //Create the alias name - var sql2 = @"insert into alias_name (id_alias, name) values (@idAlias, @name);"; - _db.Connection.Execute(sql2, new - { - idAlias = alias.DuplicateOf ?? alias.Id, - alias.Name, - }); - - if (alias.Id == 0) - { - alias.DuplicateOf = null; //It's not a duplicate anymore, we've created it in the DB - } - } - public long GetDefaultSessionId() { var sql = "select s_value from settings where lower(s_key) = 'idsession'"; @@ -124,24 +152,24 @@ public AliasQueryResult GetExact(string name, long? idSession = null, int delay var sql = @" select - n.Name as Name, - n.Name as OldName, - s.Id as Id, - s.id as Id, - s.arguments as Arguments, - s.file_name as FileName, - s.notes as Notes, - s.run_as as RunAs, - s.start_mode as StartMode, - s.working_dir as WorkingDirectory, - s.icon as Icon, + n.Name as Name,, + s.synonyms as Synonyms, + a.Id as Id, + a.arguments as Arguments, + a.file_name as FileName, + a.notes as Notes, + a.run_as as RunAs, + a.start_mode as StartMode, + a.working_dir as WorkingDirectory, + a.icon as Icon, c.exec_count as Count from - alias s + alias a left join alias_name n on s.id = n.id_alias left join stat_execution_count_v c on c.id_keyword = s.id + inner join data_alias_synonyms_v s on s.id_alias = a.id where - s.id_session = @idSession + a.id_session = @idSession and n.Name = @name order by c.exec_count desc, @@ -155,6 +183,28 @@ order by return result; } + public KeywordUsage GetHiddenKeyword(string name) + { + var sql = @" + select + a.id, + n.name, + ( + select count(id) + from alias_usage + where id = a.id + ) as count + from + alias a + inner join alias_name n on a.id = n.id_alias + where + hidden = 1 + and n.name = @name;"; + var result = _db.Connection.Query(sql, new { name }).FirstOrDefault(); + + return result; + } + public void Remove(AliasQueryResult alias) { if (alias == null) { throw new ArgumentNullException(nameof(alias), "Cannot delete NULL alias."); } @@ -175,7 +225,7 @@ public void Remove(AliasQueryResult alias) delete from alias where id in ( select a.id - from + from alias a left join alias_name an on a.id = an.id_alias where an.id_alias is null @@ -202,7 +252,7 @@ public void Remove(IEnumerable alias) delete from alias where id in ( select a.id - from + from alias a left join alias_name an on a.id = an.id_alias where an.id_alias is null @@ -264,82 +314,16 @@ update alias public void UpdateName(AliasQueryResult alias) { - if (alias.HasChangedName()) - { - var sql = @" - select id - from alias_name - where - id_alias = @id - and lower(name) = lower(@name)"; - var id = _db.Connection.Query(sql, new - { - id = alias.Id, - name = alias.OldName - }).FirstOrDefault(); - - if (id.HasValue) - { - sql = @" - update alias_name - set - name = lower(@name) - where - id = @id;"; - - _db.Connection.Execute(sql, new - { - id, - name = alias.Name - }); - } - } - } - - public KeywordUsage GetHiddenKeyword(string name) - { - var sql = @" - select - a.id, - n.name, - ( - select count(id) - from alias_usage - where id = a.id - ) as count - from - alias a - inner join alias_name n on a.id = n.id_alias - where - hidden = 1 - and n.name = @name;"; - var result = _db.Connection.Query(sql, new { name }).FirstOrDefault(); - - return result; - } - - internal IEnumerable RefreshUsage(IEnumerable results) - { - var ids = (from r in results - where r.Id != 0 - select r); - var sql = @" - select - id_alias as id, - count - from - stat_usage_per_app_v - where id_alias in @ids;"; + //Remove all names + var sql = @"delete from alias_name where id_alias = @id"; + _db.Connection.Execute(sql, new { id = alias.Id }); - var dbResults = _db.Connection.Query(sql, new { ids = results.Select(x => x.Id).ToArray() }); - - foreach (var result in results) + //Recreate new names + sql = @"insert into alias_name (id_alias, name) values (@id, @name)"; + foreach (var name in alias.GetNames()) { - result.Count = (from item in dbResults - where item.Id == result.Id - select item.Count).SingleOrDefault(); + _db.Connection.Execute(sql, new { id = alias.Id, name }); } - return results; } #endregion Methods diff --git a/src/Lanceur.Infra.SQLite/SQLiteRepository.cs b/src/Lanceur.Infra.SQLite/SQLiteRepository.cs index c43c2106..a64e529f 100644 --- a/src/Lanceur.Infra.SQLite/SQLiteRepository.cs +++ b/src/Lanceur.Infra.SQLite/SQLiteRepository.cs @@ -35,33 +35,40 @@ public SQLiteRepository( #region Methods + public ExistingNameResponse CheckNamesExist(string[] names, long? idSession = null) + { + if (!idSession.HasValue) { idSession = GetDefaultSessionId(); } + return _aliasDbAction.CheckNameExists(names, idSession.Value); + } + public IEnumerable GetAll(long? idSession = null) { if (!idSession.HasValue) { idSession = GetDefaultSessionId(); } var sql = @" select - n.Name as Name, - n.Name as OldName, - s.Id as Id, - s.id as Id, - s.arguments as Parameters, - s.file_name as FileName, - s.notes as Notes, - s.run_as as RunAs, - s.start_mode as StartMode, - s.working_dir as WorkingDirectory, - s.icon as Icon, - c.exec_count as Count + an.Name as Name, + a.Id as Id, + a.id as Id, + a.arguments as Parameters, + a.file_name as FileName, + a.notes as Notes, + a.run_as as RunAs, + a.start_mode as StartMode, + a.working_dir as WorkingDirectory, + a.icon as Icon, + c.exec_count as Count, + s.synonyms as Synonyms from - alias s - left join alias_name n on s.id = n.id_alias - left join stat_execution_count_v c on c.id_keyword = s.id + alias a + left join alias_name an on a.id = an.id_alias + left join stat_execution_count_v c on c.id_keyword = a.id + inner join data_alias_synonyms_v s on s.id_alias = a.id where - s.id_session = @idSession + a.id_session = @idSession order by c.exec_count desc, - n.name asc"; + an.name asc"; var parameters = new { idSession }; var result = DB.Connection.Query(sql, parameters); @@ -218,20 +225,15 @@ public void Remove(Session session) public void SaveOrUpdate(ref AliasQueryResult alias, long? idSession = null) { if (alias == null) { throw new ArgumentNullException(nameof(alias), $"Cannot save NULL alias."); } - if (alias.Name == null) { throw new ArgumentNullException(nameof(alias.Name), "Cannot create or update alias with no name."); } + if (alias.Synonyms == null) { throw new ArgumentNullException(nameof(alias.Name), "Cannot create or update alias with no name."); } if (alias.Id < 0) { throw new NotSupportedException($"The alias has an unexpected id. (Name: {alias.Name})"); } if (!idSession.HasValue) { idSession = GetDefaultSessionId(); } - if (alias.DuplicateOf.HasValue) - { - _log.Info($"Saving a duplicated alias. (Duplicate of: {alias.DuplicateOf})"); - _aliasDbAction.Duplicate(alias); - } - else if (alias.Id == 0 && !_aliasDbAction.CheckNameExists(alias, idSession.Value)) + if (alias.Id == 0 && !_aliasDbAction.CheckNameExists(alias, idSession.Value)) { _aliasDbAction.Create(ref alias, idSession.Value); - _log.Info($"Just created new alias. (Id: {alias.Id})"); + _log.Info($"Created new alias. (Id: {alias.Id})"); } else if (alias.Id > 0) { @@ -246,29 +248,30 @@ public IEnumerable Search(string name, long? idSession = null) var sql = @" select - n.Name as Name, - n.Name as OldName, - s.Id as Id, - s.id as Id, - s.arguments as Parameters, - s.file_name as FileName, - s.notes as Notes, - s.run_as as RunAs, - s.start_mode as StartMode, - s.working_dir as WorkingDirectory, - s.icon as Icon, - c.exec_count as Count + an.Name as Name, + a.Id as Id, + a.id as Id, + a.arguments as Parameters, + a.file_name as FileName, + a.notes as Notes, + a.run_as as RunAs, + a.start_mode as StartMode, + a.working_dir as WorkingDirectory, + a.icon as Icon, + c.exec_count as Count, + s.synonyms as Synonyms from - alias s - left join alias_name n on s.id = n.id_alias - left join stat_execution_count_v c on c.id_keyword = s.id + alias a + left join alias_name an on a.id = an.id_alias + left join stat_execution_count_v c on c.id_keyword = a.id + inner join data_alias_synonyms_v s on s.id_alias = a.id where - s.id_session = @idSession - and n.Name like @name - and s.hidden = 0 + a.id_session = @idSession + and an.Name like @name + and a.hidden = 0 order by c.exec_count desc, - n.name asc"; + an.name asc"; name = $"{name ?? string.Empty}%"; var results = DB.Connection.Query(sql, new { name, idSession }); diff --git a/src/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs b/src/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs index 260c4772..aa6b991c 100644 --- a/src/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs +++ b/src/Lanceur.Tests/BusinessLogic/AliasManagementShould.cs @@ -1,7 +1,6 @@ using Dapper; using FluentAssertions; using FluentAssertions.Execution; -using Lanceur.Core.Managers; using Lanceur.Core.Models; using Lanceur.Core.Services; using Lanceur.Infra.SQLite; @@ -20,9 +19,10 @@ public class AliasManagementShould : SQLiteTest private static AliasQueryResult BuildAlias(string name = null, RunAs runAs = RunAs.CurrentUser) { + name ??= Guid.NewGuid().ToString(); return new AliasQueryResult() { - Name = name ?? Guid.NewGuid().ToString(), + Synonyms = name, Parameters = string.Empty, FileName = @"C:\Users\jibedoubleve\AppData\Local\Programs\beekeeper-studio\Beekeeper Studioeuh.exe", RunAs = runAs, @@ -50,192 +50,142 @@ private static SQLiteRepository BuildDataService(SQLiteConnection connection) } [Fact] - public void UpdateAlias() + public void CreateAlias() { // ARRANGE - // I'm aware about SQL injection... But I guess risk is low. - var oldName = $"OLD_{Guid.NewGuid()}"; - var oldParameters = $"OLD_{Guid.NewGuid()}"; - var sql = @$" - insert into alias(id, arguments) values (1000, '{oldParameters}'); - insert into alias_name(id, id_alias, name) values (1000, 1000, '{oldName}');"; + var sql = @" + insert into alias_name(id, name, id_alias) values (1000, 'noname', null); + insert into alias_name(id, name, id_alias) values (2000, 'noname', null); + insert into alias_name(id, name, id_alias) values (3000, 'noname', null);"; var connection = BuildFreshDB(sql); var action = BuildAliasDbAction(connection); - var newName = $"NEW_{Guid.NewGuid()}"; - var newParameters = $"NEW_{Guid.NewGuid()}"; - var alias = new AliasQueryResult - { - Id = 1000, - Name = newName, - Parameters = newParameters - }; + var alias1 = BuildAlias(); + var alias2 = BuildAlias(); + var alias3 = BuildAlias(); // ACT - var act = () => action.Update(alias); + action.Create(ref alias1, 1); + action.Create(ref alias2, 1); + action.Create(ref alias3, 1); - // ASSERT + //ASSERT using (new AssertionScope()) { - act.Should().NotThrow(); - - var sql2 = @" - select - a.id as id, - an.name as name, - a.arguments as parameters - from - alias a - inner join alias_name an on a.id = an.id_alias - where - a.id = 1000"; - - var assertedAlias = connection.Query(sql2).FirstOrDefault(); - - assertedAlias.Name.Should().Be(oldName); // To update name use UpdateName - assertedAlias.Parameters.Should().Be(newParameters); + alias1.Id.Should().Be(7 + 1); + alias2.Id.Should().Be(7 + 2); + alias3.Id.Should().Be(7 + 3); + + var sql2 = "select count(*) from alias"; + var sql3 = "select count(*) from alias_name"; + + connection.ExecuteScalar(sql2).Should().Be(7 + 3); + connection.ExecuteScalar(sql3).Should().Be(7 + 6); } } [Fact] - public void CreateAlias() - { - // ARRANGE - var sql = @" + public void CreateAliasUsingService() + { + // ARRANGE + var sql = @" insert into alias_name(id, name, id_alias) values (1000, 'noname', null); insert into alias_name(id, name, id_alias) values (2000, 'noname', null); insert into alias_name(id, name, id_alias) values (3000, 'noname', null);"; - var connection = BuildFreshDB(sql); - var action = BuildAliasDbAction(connection); - - var alias1 = BuildAlias(); - var alias2 = BuildAlias(); - var alias3 = BuildAlias(); - - // ACT - action.Create(ref alias1, 1); - action.Create(ref alias2, 1); - action.Create(ref alias3, 1); - - //ASSERT - using (new AssertionScope()) - { - alias1.Id.Should().Be(7 + 1); - alias2.Id.Should().Be(7 + 2); - alias3.Id.Should().Be(7 + 3); - - var sql2 = "select count(*) from alias"; - var sql3 = "select count(*) from alias_name"; - - connection.ExecuteScalar(sql2).Should().Be(7 + 3); - connection.ExecuteScalar(sql3).Should().Be(7 + 6); - } - } - - [Fact] - public void CreateAliasWithPrivilegeUsingService() - { - var connection = BuildFreshDB(); - var service = BuildDataService(connection); - - var alias = BuildAlias("admin", RunAs.Admin); - service.SaveOrUpdate(ref alias); - - var results = service.Search("admin"); - - results.Should().HaveCount(1); - - results.ElementAt(0).RunAs.Should().Be(RunAs.Admin); + var connection = BuildFreshDB(sql); + var service = BuildDataService(connection); - } - [Fact] - public void CreateAliasUsingService() - { + var alias1 = BuildAlias(); + var alias2 = BuildAlias(); + var alias3 = BuildAlias(); - // ARRANGE - var sql = @" - insert into alias_name(id, name, id_alias) values (1000, 'noname', null); - insert into alias_name(id, name, id_alias) values (2000, 'noname', null); - insert into alias_name(id, name, id_alias) values (3000, 'noname', null);"; + // ACT + service.SaveOrUpdate(ref alias1); + service.SaveOrUpdate(ref alias2); + service.SaveOrUpdate(ref alias3); - var connection = BuildFreshDB(sql); - var service = BuildDataService(connection); + //ASSERT + var sql2 = "select count(*) from alias;"; + var sql3 = "select count(*) from alias_name;"; - var alias1 = BuildAlias(); - var alias2 = BuildAlias(); - var alias3 = BuildAlias(); + alias1.Id.Should().Be(7 + 1); + alias2.Id.Should().Be(7 + 2); + alias3.Id.Should().Be(7 + 3); - // ACT - service.SaveOrUpdate(ref alias1); - service.SaveOrUpdate(ref alias2); - service.SaveOrUpdate(ref alias3); + connection.ExecuteScalar(sql2).Should().Be(7 + 3); + connection.ExecuteScalar(sql3).Should().Be(7 + 6); + } - //ASSERT - var sql2 = "select count(*) from alias;"; - var sql3 = "select count(*) from alias_name;"; + [Fact] + public void CreateAliasWithPrivilegeUsingService() + { + var connection = BuildFreshDB(); + var service = BuildDataService(connection); - alias1.Id.Should().Be(7 + 1); - alias2.Id.Should().Be(7 + 2); - alias3.Id.Should().Be(7 + 3); + var alias = BuildAlias("admin", RunAs.Admin); + service.SaveOrUpdate(ref alias); - connection.ExecuteScalar(sql2).Should().Be(7 + 3); - connection.ExecuteScalar(sql3).Should().Be(7 + 6); - } + var results = service.Search("admin"); - [Fact] - public void RemoveAlias() - { - // ARRANGE - var connection = BuildFreshDB(); - var action = BuildAliasDbAction(connection); + results.Should().HaveCount(1); - var alias = BuildAlias(); + results.ElementAt(0).RunAs.Should().Be(RunAs.Admin); + } - // ACT - action.Create(ref alias, 1); - action.Remove(alias); + [Fact] + public void RemoveAlias() + { + // ARRANGE + var connection = BuildFreshDB(); + var action = BuildAliasDbAction(connection); - //ASSERT - var sql2 = "select count(*) from alias"; - var sql3 = "select count(*) from alias_name"; + var alias = BuildAlias(); - connection.ExecuteScalar(sql2).Should().Be(7); // Default alias are in the DB - connection.ExecuteScalar(sql3).Should().Be(7); - } + // ACT + action.Create(ref alias, 1); + action.Remove(alias); - [Fact] - public void RemoveAliasUsingService() - { - // ARRANGE - var connection = BuildFreshDB(); - var service = BuildDataService(connection); + //ASSERT + var sql2 = "select count(*) from alias"; + var sql3 = "select count(*) from alias_name"; - var alias1 = BuildAlias("one"); - var alias2 = BuildAlias("two"); - var alias3 = BuildAlias("three"); + connection.ExecuteScalar(sql2).Should().Be(7); // Default alias are in the DB + connection.ExecuteScalar(sql3).Should().Be(7); + } - // ACT - service.SaveOrUpdate(ref alias1); - service.SaveOrUpdate(ref alias2); - service.SaveOrUpdate(ref alias3); - service.Remove(alias1); + [Fact] + public void RemoveAliasUsingService() + { + // ARRANGE + var connection = BuildFreshDB(); + var service = BuildDataService(connection); - //ASSERT - var sql2 = "select count(*) from alias"; - var sql3 = "select count(*) from alias_name"; + var alias1 = BuildAlias("one"); + var alias2 = BuildAlias("two"); + var alias3 = BuildAlias("three"); - alias1.Id.Should().BeGreaterThan(0); - connection.ExecuteScalar(sql2).Should().Be(9); - connection.ExecuteScalar(sql3).Should().Be(9); - } + // ACT + service.SaveOrUpdate(ref alias1); + service.SaveOrUpdate(ref alias2); + service.SaveOrUpdate(ref alias3); + service.Remove(alias1); + + //ASSERT + var sql2 = "select count(*) from alias"; + var sql3 = "select count(*) from alias_name"; + + alias1.Id.Should().BeGreaterThan(0); + connection.ExecuteScalar(sql2).Should().Be(9); + connection.ExecuteScalar(sql3).Should().Be(9); + } - [Fact] - public void RemoveAliasWithDbActionSQL() - { - // ARRANGE - var sql = @" + [Fact] + public void RemoveAliasWithDbActionSQL() + { + // ARRANGE + var sql = @" insert into alias (id, arguments, file_name, id_session) values (256, 'no args', 'no file name', 1); insert into alias_name(name, id_alias) values ('noname', 256); @@ -244,26 +194,26 @@ public void RemoveAliasWithDbActionSQL() insert into alias (id, arguments, file_name, id_session) values (258, 'no args', 'no file name', 1); insert into alias_name(name, id_alias) values ('noname', 258);"; - var connection = BuildFreshDB(sql); + var connection = BuildFreshDB(sql); - var action = BuildAliasDbAction(connection); + var action = BuildAliasDbAction(connection); - // ACT - action.Remove(new AliasQueryResult() { Id = 256 }); + // ACT + action.Remove(new AliasQueryResult() { Id = 256 }); - // ASSERT - var sql2 = "select count(*) from alias where id = 256"; - connection.ExecuteScalar(sql2).Should().Be(0); + // ASSERT + var sql2 = "select count(*) from alias where id = 256"; + connection.ExecuteScalar(sql2).Should().Be(0); - var sql3 = "select count(*) from alias_name where id_alias = 256"; - connection.ExecuteScalar(sql3).Should().Be(0); - } + var sql3 = "select count(*) from alias_name where id_alias = 256"; + connection.ExecuteScalar(sql3).Should().Be(0); + } - [Fact] - public void RemoveAliasWithServiceSQL() - { - // ARRANGE - var sql = @" + [Fact] + public void RemoveAliasWithServiceSQL() + { + // ARRANGE + var sql = @" insert into alias (id, arguments, file_name, id_session) values (256, 'no args', 'no file name', 1); insert into alias_name(name, id_alias) values ('noname', 256); @@ -272,21 +222,21 @@ public void RemoveAliasWithServiceSQL() insert into alias (id, arguments, file_name, id_session) values (258, 'no args', 'no file name', 1); insert into alias_name(name, id_alias) values ('noname', 258);"; - var connection = BuildFreshDB(sql); - - var service = BuildDataService(connection); + var connection = BuildFreshDB(sql); - // ACT - service.Remove(new AliasQueryResult() { Id = 256 }); + var service = BuildDataService(connection); - // ASSERT - var sql2 = "select count(*) from alias where id = 256"; - connection.ExecuteScalar(sql2).Should().Be(0); + // ACT + service.Remove(new AliasQueryResult() { Id = 256 }); - var sql3 = "select count(*) from alias_name where id_alias = 256"; - connection.ExecuteScalar(sql3).Should().Be(0); - } + // ASSERT + var sql2 = "select count(*) from alias where id = 256"; + connection.ExecuteScalar(sql2).Should().Be(0); - #endregion Methods + var sql3 = "select count(*) from alias_name where id_alias = 256"; + connection.ExecuteScalar(sql3).Should().Be(0); } - } \ No newline at end of file + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Lanceur.Tests/Models/QueryResultShould.cs b/src/Lanceur.Tests/Models/QueryResultShould.cs index e9c3e8a7..044979f5 100644 --- a/src/Lanceur.Tests/Models/QueryResultShould.cs +++ b/src/Lanceur.Tests/Models/QueryResultShould.cs @@ -1,4 +1,5 @@ using FluentAssertions; +using FluentAssertions.Execution; using Lanceur.Core.Models; using Xunit; @@ -33,29 +34,23 @@ public void HaveZeroCountByDefault() new TestQueryResult().Count.Should().Be(0); } - [Theory] - [InlineData("", "bonjour tout le monde")] - [InlineData("hello world", "bonjour tout le monde")] - public void HaveOldNameUnchangedWhenUpdateName(string expected, string actual) - { - var query = new TestQueryResult() - { - Name = expected - }; - query.Name = actual; - query.OldName.Should().Be(expected); - } - [Fact] - public void HaveOldNameChangedWhenNullWasProvidedTheFirstTime() + public void HaveTrimmedResultInSynonyms() { - var name = "bonjour tout le monde"; - var query = new TestQueryResult() { Name = null }; - query.Name = name; - - query.OldName.Should().Be(name); + // arrange + var synonyms = "un, deux,trois,quatre,cinq"; + var queryResult = new AliasQueryResult() { Synonyms = synonyms }; + // act + var names = queryResult.GetNames(); + // assert + using (new AssertionScope()) + { + names.Should().HaveCount(5); + names.Select(x => x.Should().NotStartWith(" ")); + names.Select(x => x.Should().NotEndWith(" ")); + } } #endregion Methods diff --git a/src/Lanceur/Lanceur.csproj b/src/Lanceur/Lanceur.csproj index ec520aba..7889d151 100644 --- a/src/Lanceur/Lanceur.csproj +++ b/src/Lanceur/Lanceur.csproj @@ -12,6 +12,7 @@ + @@ -33,6 +34,7 @@ + diff --git a/src/Lanceur/SQL/script-0.11.sql b/src/Lanceur/SQL/script-0.11.sql new file mode 100644 index 00000000..89e8cedc --- /dev/null +++ b/src/Lanceur/SQL/script-0.11.sql @@ -0,0 +1,7 @@ +drop view if exists data_alias_synonyms_v; +create view data_alias_synonyms_v as + select + id_alias as id_alias, + group_concat(name, ', ') as synonyms + from alias_name + group by id_alias; \ No newline at end of file diff --git a/src/Lanceur/Views/KeywordsView.xaml b/src/Lanceur/Views/KeywordsView.xaml index 84b5c8e3..78dac2a2 100644 --- a/src/Lanceur/Views/KeywordsView.xaml +++ b/src/Lanceur/Views/KeywordsView.xaml @@ -85,14 +85,7 @@ BorderBrush="{StaticResource DialogBorderBrush}" BorderThickness="1" ItemTemplate="{StaticResource MinimalQueryResultTemplate}" - SelectionChanged="OnAliasSelectionChanged"> - - - + SelectionChanged="OnAliasSelectionChanged" />