From fdb081b51b0bc1a091799ec911361982aa51c723 Mon Sep 17 00:00:00 2001 From: Aaron Sherber Date: Thu, 25 Apr 2019 15:41:29 -0400 Subject: [PATCH 1/5] Include the Engine when cloning a FromClause --- QueryBuilder.Tests/GeneralTests.cs | 45 ++++++++++++++++++++++++++++++ QueryBuilder/Clauses/FromClause.cs | 1 + 2 files changed, 46 insertions(+) diff --git a/QueryBuilder.Tests/GeneralTests.cs b/QueryBuilder.Tests/GeneralTests.cs index d25fcc84..66375e9b 100644 --- a/QueryBuilder.Tests/GeneralTests.cs +++ b/QueryBuilder.Tests/GeneralTests.cs @@ -160,5 +160,50 @@ public void WrapWithMultipleSpaces() Assert.Equal("[My Table One] AS [Table One]", compiler.Wrap("My Table One as Table One")); } + + [Fact] + public void CompilerSpecificFrom() + { + var query = new Query() + .ForSqlServer(q => q.From("mssql")) + .ForPostgreSql(q => q.From("pgsql")) + .ForMySql(q => q.From("mysql")); + var engines = new[] { EngineCodes.SqlServer, EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal("SELECT * FROM [mssql]", c[EngineCodes.SqlServer].RawSql); + Assert.Equal("SELECT * FROM \"pgsql\"", c[EngineCodes.PostgreSql].RawSql); + Assert.Equal("SELECT * FROM `mysql`", c[EngineCodes.MySql].RawSql); + } + + [Fact] + public void CompilerSpecificFromRaw() + { + var query = new Query() + .ForSqlServer(q => q.FromRaw("[mssql]")) + .ForPostgreSql(q => q.FromRaw("[pgsql]")) + .ForMySql(q => q.FromRaw("[mysql]")); + var engines = new[] { EngineCodes.SqlServer, EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal("SELECT * FROM [mssql]", c[EngineCodes.SqlServer].RawSql); + Assert.Equal("SELECT * FROM \"pgsql\"", c[EngineCodes.PostgreSql].RawSql); + Assert.Equal("SELECT * FROM `mysql`", c[EngineCodes.MySql].RawSql); + } + + [Fact] + public void CompilerSpecificFromMixed() + { + var query = new Query() + .ForSqlServer(q => q.From("mssql")) + .ForPostgreSql(q => q.FromRaw("[pgsql]")) + .ForMySql(q => q.From("mysql")); + var engines = new[] { EngineCodes.SqlServer, EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal("SELECT * FROM [mssql]", c[EngineCodes.SqlServer].RawSql); + Assert.Equal("SELECT * FROM \"pgsql\"", c[EngineCodes.PostgreSql].RawSql); + Assert.Equal("SELECT * FROM `mysql`", c[EngineCodes.MySql].RawSql); + } } } diff --git a/QueryBuilder/Clauses/FromClause.cs b/QueryBuilder/Clauses/FromClause.cs index fb9c51b8..9b21a50b 100644 --- a/QueryBuilder/Clauses/FromClause.cs +++ b/QueryBuilder/Clauses/FromClause.cs @@ -40,6 +40,7 @@ public override AbstractClause Clone() { return new FromClause { + Engine = Engine, Alias = Alias, Table = Table, Component = Component, From 293184a2ce695e7eecd1e460289be74793ab442d Mon Sep 17 00:00:00 2001 From: Aaron Sherber Date: Sat, 27 Apr 2019 13:39:06 -0400 Subject: [PATCH 2/5] Add AddOrReplaceComponent and use in From GetOneComponent prioritizes engine --- QueryBuilder.Tests/GeneralTests.cs | 61 ++++++++++++++++++++++++++++++ QueryBuilder/BaseQuery.cs | 41 ++++++++++++++------ 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/QueryBuilder.Tests/GeneralTests.cs b/QueryBuilder.Tests/GeneralTests.cs index 66375e9b..893a4ec0 100644 --- a/QueryBuilder.Tests/GeneralTests.cs +++ b/QueryBuilder.Tests/GeneralTests.cs @@ -1,6 +1,8 @@ using SqlKata.Compilers; using SqlKata.Extensions; using SqlKata.Tests.Infrastructure; +using System; +using System.Linq; using Xunit; namespace SqlKata.Tests @@ -205,5 +207,64 @@ public void CompilerSpecificFromMixed() Assert.Equal("SELECT * FROM \"pgsql\"", c[EngineCodes.PostgreSql].RawSql); Assert.Equal("SELECT * FROM `mysql`", c[EngineCodes.MySql].RawSql); } + + [Fact] + public void OneFromPerEngine() + { + var query = new Query("generic") + .ForSqlServer(q => q.From("dnu")) + .ForSqlServer(q => q.From("mssql")); + var engines = new[] { EngineCodes.SqlServer, EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal(2, query.Clauses.OfType().Count()); + Assert.Equal("SELECT * FROM [mssql]", c[EngineCodes.SqlServer].RawSql); + Assert.Equal("SELECT * FROM \"generic\"", c[EngineCodes.PostgreSql].RawSql); + Assert.Equal("SELECT * FROM `generic`", c[EngineCodes.MySql].RawSql); + } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "mssql")] + [InlineData("original", null)] + [InlineData("original", "mssql")] + public void AddOrReplace_Works(string table, string engine) + { + var query = new Query(); + if (table != null) + query.From(table); + query.AddOrReplaceComponent("from", new FromClause() { Table = "updated", Engine = engine }); + var froms = query.Clauses.OfType(); + + Assert.Single(froms); + Assert.Equal("updated", froms.Single().Table); + } + + [Theory] + [InlineData(null, "generic")] + [InlineData(EngineCodes.SqlServer, "mssql")] + [InlineData(EngineCodes.MySql, "generic")] + public void GetOneComponent_Prefers_Engine(string engine, string column) + { + var query = new Query() + .Where("generic", "foo") + .ForSqlServer(q => q.Where("mssql", "foo")); + + var where = query.GetOneComponent("where", engine) as BasicCondition; + + Assert.NotNull(where); + Assert.Equal(column, where.Column); + } + + [Fact] + public void AddOrReplace_Throws_MoreThanOne() + { + var query = new Query() + .Where("a", "b") + .Where("c", "d"); + + Action act = () => query.AddOrReplaceComponent("where", new BasicCondition()); + Assert.Throws(act); + } } } diff --git a/QueryBuilder/BaseQuery.cs b/QueryBuilder/BaseQuery.cs index a08a5652..9da54bb0 100644 --- a/QueryBuilder/BaseQuery.cs +++ b/QueryBuilder/BaseQuery.cs @@ -82,6 +82,28 @@ public Q AddComponent(string component, AbstractClause clause, string engineCode return (Q)this; } + /// + /// If the query already contains a clause for the given component + /// and engine, replace it with the specified clause. Otherwise, just + /// add the clause. + /// + /// + /// + /// + /// + public Q AddOrReplaceComponent(string component, AbstractClause clause, string engineCode = null) + { + engineCode = engineCode ?? EngineScope; + + var current = GetComponents(component).SingleOrDefault(c => c.Engine == engineCode); + if (current != null) + Clauses.Remove(current); + + return AddComponent(component, clause, engineCode); + } + + + /// /// Get the list of clauses for a component. /// @@ -123,13 +145,10 @@ public List GetComponents(string component, string engineCode = /// public C GetOneComponent(string component, string engineCode = null) where C : AbstractClause { - if (engineCode == null) - { - engineCode = EngineScope; - } + engineCode = engineCode ?? EngineScope; - return GetComponents(component, engineCode) - .FirstOrDefault(); + var all = GetComponents(component, engineCode); + return all.FirstOrDefault(c => c.Engine == engineCode) ?? all.FirstOrDefault(c => c.Engine == null); } /// @@ -149,7 +168,7 @@ public AbstractClause GetOneComponent(string component, string engineCode = null } /// - /// Return wether the query has clauses for a component. + /// Return whether the query has clauses for a component. /// /// /// @@ -247,9 +266,9 @@ protected bool GetNot() /// public Q From(string table) { - return ClearComponent("from").AddComponent("from", new FromClause + return AddOrReplaceComponent("from", new FromClause { - Table = table + Table = table, }); } @@ -263,7 +282,7 @@ public Q From(Query query, string alias = null) query.As(alias); }; - return ClearComponent("from").AddComponent("from", new QueryFromClause + return AddOrReplaceComponent("from", new QueryFromClause { Query = query }); @@ -271,7 +290,7 @@ public Q From(Query query, string alias = null) public Q FromRaw(string sql, params object[] bindings) { - return ClearComponent("from").AddComponent("from", new RawFromClause + return AddOrReplaceComponent("from", new RawFromClause { Expression = sql, Bindings = bindings, From 0576659ecccf9a043fd59975b7ab8b278eddde92 Mon Sep 17 00:00:00 2001 From: Aaron Sherber Date: Sun, 28 Apr 2019 00:01:40 -0400 Subject: [PATCH 3/5] Use AddOrReplaceComponent in Limit and Offset --- QueryBuilder.Tests/GeneralTests.cs | 82 +++++++++++++++++++++ QueryBuilder/Compilers/SqlServerCompiler.cs | 2 +- QueryBuilder/Query.cs | 38 +++++----- 3 files changed, 101 insertions(+), 21 deletions(-) diff --git a/QueryBuilder.Tests/GeneralTests.cs b/QueryBuilder.Tests/GeneralTests.cs index 893a4ec0..ec75b529 100644 --- a/QueryBuilder.Tests/GeneralTests.cs +++ b/QueryBuilder.Tests/GeneralTests.cs @@ -266,5 +266,87 @@ public void AddOrReplace_Throws_MoreThanOne() Action act = () => query.AddOrReplaceComponent("where", new BasicCondition()); Assert.Throws(act); } + + [Fact] + public void OneLimitPerEngine() + { + var query = new Query("mytable") + .ForSqlServer(q => q.Limit(5)) + .ForSqlServer(q => q.Limit(10)); + + var limits = query.GetComponents("limit", EngineCodes.SqlServer); + Assert.Single(limits); + Assert.Equal(10, limits.Single().Limit); + } + + [Fact] + public void CompilerSpecificLimit() + { + var query = new Query("mytable") + .ForSqlServer(q => q.Limit(5)) + .ForPostgreSql(q => q.Limit(10)); + + var engines = new[] { EngineCodes.SqlServer, EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal(2, query.GetComponents("limit").Count()); + Assert.Equal("SELECT TOP (5) * FROM [mytable]", c[EngineCodes.SqlServer].ToString()); + Assert.Equal("SELECT * FROM \"mytable\" LIMIT 10", c[EngineCodes.PostgreSql].ToString()); + Assert.Equal("SELECT * FROM `mytable`", c[EngineCodes.MySql].ToString()); + } + + [Fact] + public void Limit_Preserves_Offset() + { + var query = new Query("mytable") + .Offset(5); + query.Limit(10); + + var limits = query.GetComponents("limit"); + Assert.Single(limits); + Assert.Equal(5, limits.Single().Offset); + Assert.Equal(10, limits.Single().Limit); + } + + [Fact] + public void OneOffsetPerEngine() + { + var query = new Query("mytable") + .ForSqlServer(q => q.Offset(5)) + .ForSqlServer(q => q.Offset(10)); + + var limits = query.GetComponents("limit", EngineCodes.SqlServer); + Assert.Single(limits); + Assert.Equal(10, limits.Single().Offset); + } + + [Fact] + public void CompilerSpecificOffset() + { + var query = new Query("mytable") + .ForMySql(q => q.Offset(5)) + .ForPostgreSql(q => q.Offset(10)); + + var engines = new[] { EngineCodes.SqlServer, EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal(2, query.GetComponents("limit").Count()); + Assert.Equal("SELECT * FROM `mytable` LIMIT 18446744073709551615 OFFSET 5", c[EngineCodes.MySql].ToString()); + Assert.Equal("SELECT * FROM \"mytable\" OFFSET 10", c[EngineCodes.PostgreSql].ToString()); + Assert.Equal("SELECT * FROM [mytable]", c[EngineCodes.SqlServer].ToString()); + } + + [Fact] + public void Offset_Preserves_Limit() + { + var query = new Query("mytable") + .Limit(5); + query.Offset(10); + + var limits = query.GetComponents("limit"); + Assert.Single(limits); + Assert.Equal(10, limits.Single().Offset); + Assert.Equal(5, limits.Single().Limit); + } } } diff --git a/QueryBuilder/Compilers/SqlServerCompiler.cs b/QueryBuilder/Compilers/SqlServerCompiler.cs index 65c67ef0..13bc8264 100644 --- a/QueryBuilder/Compilers/SqlServerCompiler.cs +++ b/QueryBuilder/Compilers/SqlServerCompiler.cs @@ -14,7 +14,7 @@ public SqlServerCompiler() protected override SqlResult CompileSelectQuery(Query query) { - if (!UseLegacyPagination || !query.HasOffset()) + if (!UseLegacyPagination || !query.HasOffset(EngineCode)) { return base.CompileSelectQuery(query); } diff --git a/QueryBuilder/Query.cs b/QueryBuilder/Query.cs index 7ddeb65e..6647280f 100755 --- a/QueryBuilder/Query.cs +++ b/QueryBuilder/Query.cs @@ -25,6 +25,7 @@ public Query(string table, string comment = null) : base() public bool HasOffset(string engineCode = null) { + engineCode = engineCode ?? EngineScope; var limitOffset = this.GetOneComponent("limit", engineCode); return limitOffset?.HasOffset() ?? false; @@ -32,6 +33,7 @@ public bool HasOffset(string engineCode = null) public bool HasLimit(string engineCode = null) { + engineCode = engineCode ?? EngineScope; var limitOffset = this.GetOneComponent("limit", engineCode); return limitOffset?.HasLimit() ?? false; @@ -39,6 +41,7 @@ public bool HasLimit(string engineCode = null) internal int GetOffset(string engineCode = null) { + engineCode = engineCode ?? EngineScope; var limitOffset = this.GetOneComponent("limit", engineCode); return limitOffset?.Offset ?? 0; @@ -46,6 +49,7 @@ internal int GetOffset(string engineCode = null) internal int GetLimit(string engineCode = null) { + engineCode = engineCode ?? EngineScope; var limitOffset = this.GetOneComponent("limit", engineCode); return limitOffset?.Limit ?? 0; @@ -134,34 +138,28 @@ public Query WithRaw(string alias, string sql, params object[] bindings) public Query Limit(int value) { - var clause = GetOneComponent("limit", EngineScope) as LimitOffset; - - if (clause != null) - { - clause.Limit = value; - return this; - } - - return AddComponent("limit", new LimitOffset + var newClause = new LimitOffset { Limit = value - }); + }; + + if (GetOneComponent("limit", EngineScope) is LimitOffset currentClause) + newClause.Offset = currentClause.Offset; + + return AddOrReplaceComponent("limit", newClause); } public Query Offset(int value) { - var clause = GetOneComponent("limit", EngineScope) as LimitOffset; - - if (clause != null) - { - clause.Offset = value; - return this; - } - - return AddComponent("limit", new LimitOffset + var newClause = new LimitOffset { Offset = value - }); + }; + + if (GetOneComponent("limit", EngineScope) is LimitOffset currentClause) + newClause.Limit = currentClause.Limit; + + return AddOrReplaceComponent("limit", newClause); } /// From 190aa7f529f1bc87457439e348d909c9d2e7c4d8 Mon Sep 17 00:00:00 2001 From: Aaron Sherber Date: Sun, 28 Apr 2019 14:20:24 -0400 Subject: [PATCH 4/5] Add a test --- QueryBuilder.Tests/GeneralTests.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/QueryBuilder.Tests/GeneralTests.cs b/QueryBuilder.Tests/GeneralTests.cs index ec75b529..c1fd9823 100644 --- a/QueryBuilder.Tests/GeneralTests.cs +++ b/QueryBuilder.Tests/GeneralTests.cs @@ -348,5 +348,20 @@ public void Offset_Preserves_Limit() Assert.Equal(10, limits.Single().Offset); Assert.Equal(5, limits.Single().Limit); } + + [Fact] + public void LimitOffset_Takes_Generic_If_Needed() + { + var query = new Query("mytable") + .Limit(5) + .Offset(10) + .ForPostgreSql(q => q.Limit(20)); + + var engines = new[] { EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal("SELECT * FROM `mytable` LIMIT 5 OFFSET 10", c[EngineCodes.MySql].ToString()); + Assert.Equal("SELECT * FROM \"mytable\" LIMIT 20 OFFSET 10", c[EngineCodes.PostgreSql].ToString()); + } } } From 9e16e9d13895e2454d6fd5b414fd63e3fba51e80 Mon Sep 17 00:00:00 2001 From: Aaron Sherber Date: Tue, 30 Apr 2019 20:23:32 -0400 Subject: [PATCH 5/5] Turn LimitOffset into Limit and Offset --- QueryBuilder.Tests/GeneralTests.cs | 69 ++++++++++++++++++---------- QueryBuilder/Clauses/LimitClause.cs | 48 ++----------------- QueryBuilder/Clauses/OffsetClause.cs | 35 ++++++++++++++ QueryBuilder/Query.cs | 36 ++++----------- 4 files changed, 94 insertions(+), 94 deletions(-) create mode 100644 QueryBuilder/Clauses/OffsetClause.cs diff --git a/QueryBuilder.Tests/GeneralTests.cs b/QueryBuilder.Tests/GeneralTests.cs index c1fd9823..7d2168e9 100644 --- a/QueryBuilder.Tests/GeneralTests.cs +++ b/QueryBuilder.Tests/GeneralTests.cs @@ -274,7 +274,7 @@ public void OneLimitPerEngine() .ForSqlServer(q => q.Limit(5)) .ForSqlServer(q => q.Limit(10)); - var limits = query.GetComponents("limit", EngineCodes.SqlServer); + var limits = query.GetComponents("limit", EngineCodes.SqlServer); Assert.Single(limits); Assert.Equal(10, limits.Single().Limit); } @@ -295,19 +295,6 @@ public void CompilerSpecificLimit() Assert.Equal("SELECT * FROM `mytable`", c[EngineCodes.MySql].ToString()); } - [Fact] - public void Limit_Preserves_Offset() - { - var query = new Query("mytable") - .Offset(5); - query.Limit(10); - - var limits = query.GetComponents("limit"); - Assert.Single(limits); - Assert.Equal(5, limits.Single().Offset); - Assert.Equal(10, limits.Single().Limit); - } - [Fact] public void OneOffsetPerEngine() { @@ -315,7 +302,7 @@ public void OneOffsetPerEngine() .ForSqlServer(q => q.Offset(5)) .ForSqlServer(q => q.Offset(10)); - var limits = query.GetComponents("limit", EngineCodes.SqlServer); + var limits = query.GetComponents("offset", EngineCodes.SqlServer); Assert.Single(limits); Assert.Equal(10, limits.Single().Offset); } @@ -330,27 +317,29 @@ public void CompilerSpecificOffset() var engines = new[] { EngineCodes.SqlServer, EngineCodes.MySql, EngineCodes.PostgreSql }; var c = Compilers.Compile(engines, query); - Assert.Equal(2, query.GetComponents("limit").Count()); + Assert.Equal(2, query.GetComponents("offset").Count()); Assert.Equal("SELECT * FROM `mytable` LIMIT 18446744073709551615 OFFSET 5", c[EngineCodes.MySql].ToString()); Assert.Equal("SELECT * FROM \"mytable\" OFFSET 10", c[EngineCodes.PostgreSql].ToString()); Assert.Equal("SELECT * FROM [mytable]", c[EngineCodes.SqlServer].ToString()); } [Fact] - public void Offset_Preserves_Limit() + public void Limit_Takes_Generic_If_Needed() { var query = new Query("mytable") - .Limit(5); - query.Offset(10); + .Limit(5) + .Offset(10) + .ForPostgreSql(q => q.Offset(20)); - var limits = query.GetComponents("limit"); - Assert.Single(limits); - Assert.Equal(10, limits.Single().Offset); - Assert.Equal(5, limits.Single().Limit); + var engines = new[] { EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal("SELECT * FROM `mytable` LIMIT 5 OFFSET 10", c[EngineCodes.MySql].ToString()); + Assert.Equal("SELECT * FROM \"mytable\" LIMIT 5 OFFSET 20", c[EngineCodes.PostgreSql].ToString()); } [Fact] - public void LimitOffset_Takes_Generic_If_Needed() + public void Offset_Takes_Generic_If_Needed() { var query = new Query("mytable") .Limit(5) @@ -363,5 +352,37 @@ public void LimitOffset_Takes_Generic_If_Needed() Assert.Equal("SELECT * FROM `mytable` LIMIT 5 OFFSET 10", c[EngineCodes.MySql].ToString()); Assert.Equal("SELECT * FROM \"mytable\" LIMIT 20 OFFSET 10", c[EngineCodes.PostgreSql].ToString()); } + + [Fact] + public void Can_Change_Generic_Limit_After_SpecificOffset() + { + var query = new Query("mytable") + .Limit(5) + .Offset(10) + .ForPostgreSql(q => q.Offset(20)) + .Limit(7); + + var engines = new[] { EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal("SELECT * FROM `mytable` LIMIT 7 OFFSET 10", c[EngineCodes.MySql].ToString()); + Assert.Equal("SELECT * FROM \"mytable\" LIMIT 7 OFFSET 20", c[EngineCodes.PostgreSql].ToString()); + } + + [Fact] + public void Can_Change_Generic_Offset_After_SpecificLimit() + { + var query = new Query("mytable") + .Limit(5) + .Offset(10) + .ForPostgreSql(q => q.Limit(20)) + .Offset(7); + + var engines = new[] { EngineCodes.MySql, EngineCodes.PostgreSql }; + var c = Compilers.Compile(engines, query); + + Assert.Equal("SELECT * FROM `mytable` LIMIT 5 OFFSET 7", c[EngineCodes.MySql].ToString()); + Assert.Equal("SELECT * FROM \"mytable\" LIMIT 20 OFFSET 7", c[EngineCodes.PostgreSql].ToString()); + } } } diff --git a/QueryBuilder/Clauses/LimitClause.cs b/QueryBuilder/Clauses/LimitClause.cs index 4f274c6e..b37d5b29 100644 --- a/QueryBuilder/Clauses/LimitClause.cs +++ b/QueryBuilder/Clauses/LimitClause.cs @@ -1,34 +1,13 @@ namespace SqlKata { - public class LimitOffset : AbstractClause + public class LimitClause : AbstractClause { private int _limit; - private int _offset; - + public int Limit { get => _limit; - - set - { - if (value > 0) - { - _limit = value; - } - } - } - - public int Offset - { - get => _offset; - - set - { - if (value > 0) - { - _offset = value; - } - } + set => _limit = value > 0 ? value : _limit; } public bool HasLimit() @@ -36,35 +15,18 @@ public bool HasLimit() return _limit > 0; } - public bool HasOffset() - { - return _offset > 0; - } - - public LimitOffset ClearLimit() + public LimitClause Clear() { _limit = 0; return this; } - public LimitOffset ClearOffset() - { - _offset = 0; - return this; - } - - public LimitOffset Clear() - { - return ClearLimit().ClearOffset(); - } - /// public override AbstractClause Clone() { - return new LimitOffset + return new LimitClause { Engine = Engine, - Offset = Offset, Limit = Limit, Component = Component, }; diff --git a/QueryBuilder/Clauses/OffsetClause.cs b/QueryBuilder/Clauses/OffsetClause.cs new file mode 100644 index 00000000..39fe8b4e --- /dev/null +++ b/QueryBuilder/Clauses/OffsetClause.cs @@ -0,0 +1,35 @@ +namespace SqlKata +{ + public class OffsetClause : AbstractClause + { + private int _offset; + + public int Offset + { + get => _offset; + set => _offset = value > 0 ? value : _offset; + } + + public bool HasOffset() + { + return _offset > 0; + } + + public OffsetClause Clear() + { + _offset = 0; + return this; + } + + /// + public override AbstractClause Clone() + { + return new OffsetClause + { + Engine = Engine, + Offset = Offset, + Component = Component, + }; + } + } +} \ No newline at end of file diff --git a/QueryBuilder/Query.cs b/QueryBuilder/Query.cs index 6647280f..2c353292 100755 --- a/QueryBuilder/Query.cs +++ b/QueryBuilder/Query.cs @@ -23,36 +23,24 @@ public Query(string table, string comment = null) : base() } - public bool HasOffset(string engineCode = null) - { - engineCode = engineCode ?? EngineScope; - var limitOffset = this.GetOneComponent("limit", engineCode); - - return limitOffset?.HasOffset() ?? false; - } + public bool HasOffset(string engineCode = null) => GetOffset(engineCode) > 0; - public bool HasLimit(string engineCode = null) - { - engineCode = engineCode ?? EngineScope; - var limitOffset = this.GetOneComponent("limit", engineCode); - - return limitOffset?.HasLimit() ?? false; - } + public bool HasLimit(string engineCode = null) => GetLimit(engineCode) > 0; internal int GetOffset(string engineCode = null) { engineCode = engineCode ?? EngineScope; - var limitOffset = this.GetOneComponent("limit", engineCode); + var offset = this.GetOneComponent("offset", engineCode); - return limitOffset?.Offset ?? 0; + return offset?.Offset ?? 0; } internal int GetLimit(string engineCode = null) { engineCode = engineCode ?? EngineScope; - var limitOffset = this.GetOneComponent("limit", engineCode); + var limit = this.GetOneComponent("limit", engineCode); - return limitOffset?.Limit ?? 0; + return limit?.Limit ?? 0; } public override Query Clone() @@ -138,28 +126,22 @@ public Query WithRaw(string alias, string sql, params object[] bindings) public Query Limit(int value) { - var newClause = new LimitOffset + var newClause = new LimitClause { Limit = value }; - if (GetOneComponent("limit", EngineScope) is LimitOffset currentClause) - newClause.Offset = currentClause.Offset; - return AddOrReplaceComponent("limit", newClause); } public Query Offset(int value) { - var newClause = new LimitOffset + var newClause = new OffsetClause { Offset = value }; - if (GetOneComponent("limit", EngineScope) is LimitOffset currentClause) - newClause.Limit = currentClause.Limit; - - return AddOrReplaceComponent("limit", newClause); + return AddOrReplaceComponent("offset", newClause); } ///