diff --git a/SQLinq/Dialect/MySqlDialect.cs b/SQLinq/Dialect/MySqlDialect.cs new file mode 100644 index 0000000..7060367 --- /dev/null +++ b/SQLinq/Dialect/MySqlDialect.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SQLinq.Dialect +{ + public class MySqlDialect : ISqlDialect + { + const string _Space = " "; + const string Identifier = "`"; + + public object ConvertParameterValue(object value) + { + if (value is bool) + { + return (bool)value ? 1 : 0; + } + + return value; + } + + public string ParameterPrefix => "@"; + + + public string ParseTableName(string tableName) + { + if (!tableName.StartsWith(Identifier)) + { + return $"{Identifier}{tableName}{Identifier}"; + } + + return tableName; + } + + public string ParseColumnName(string columnName) + { + if (!columnName.StartsWith(Identifier) && !columnName.Contains(".")) + { + return $"{Identifier}{columnName}{Identifier}"; + } + + return columnName; + } + + public void AssertSkip(SQLinq sqLinq) + { + if (sqLinq.OrderByExpressions.Count == 0) + { + throw new NotSupportedException("SQLinq: Skip can only be performed if OrderBy is specified."); + } + } + + public string ToQuery(SQLinqSelectResult selectResult) + { + var orderby = DialectProvider.ConcatFieldArray(selectResult.OrderBy); + + var groupby = DialectProvider.ConcatFieldArray(selectResult.GroupBy); + + var sb = new StringBuilder(); + + if (selectResult.Distinct == true) + { + sb.Append("DISTINCT "); + } + + // SELECT + sb.Append(DialectProvider.ConcatFieldArray(selectResult.Select)); + + sb.Append(" FROM "); + + sb.Append(selectResult.Table); + + if (selectResult.Join != null) + { + foreach (var j in selectResult.Join) + { + sb.Append(_Space); + sb.Append(j); + } + } + + if (!string.IsNullOrEmpty(selectResult.Where)) + { + sb.Append(" WHERE "); + sb.Append(selectResult.Where); + } + + if (!string.IsNullOrEmpty(groupby)) + { + sb.Append(" GROUP BY "); + sb.Append(groupby); + } + + if (!string.IsNullOrEmpty(selectResult.Having)) + { + sb.Append(" HAVING "); + sb.Append(selectResult.Having); + } + + var sqlOrderBy = string.Empty; + if (orderby.Length > 0) + { + sqlOrderBy = " ORDER BY " + orderby; + sb.Append(sqlOrderBy); + } + + if (selectResult.Take != null) + { + if (selectResult.Skip != null) + { + sb.Append($" LIMIT {selectResult.Take} OFFSET {selectResult.Skip}"); + } + else + { + sb.Append($" LIMIT {selectResult.Take}"); + } + } + else + { + if (selectResult.Skip != null) + { + sb.Append($" LIMIT {long.MaxValue} OFFSET {selectResult.Skip}"); + } + } + + return $"SELECT {sb}"; + } + } +} diff --git a/SQLinq/SQLinq.csproj b/SQLinq/SQLinq.csproj index 4cd7f13..1736de0 100644 --- a/SQLinq/SQLinq.csproj +++ b/SQLinq/SQLinq.csproj @@ -55,6 +55,7 @@ + diff --git a/SQLinqTest/SQLinqTest.cs b/SQLinqTest/SQLinqTest.cs index f006407..710b7e2 100644 --- a/SQLinqTest/SQLinqTest.cs +++ b/SQLinqTest/SQLinqTest.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using SQLinq.Dialect; namespace SQLinqTest { @@ -41,6 +42,30 @@ public void SQLinqTest_001() Assert.AreEqual("[Column With Spaces] AS [ColumnWithSpaces]", result.Select[6]); } + [TestMethod] + public void SQLinqTest_Mysql_001() + { + var query = new SQLinq(DialectProvider.Create()).Where(d => d.Age == 12); + + var result = (SQLinqSelectResult)query.ToSQL(); + + Assert.AreEqual("`Person`", result.Table); + + Assert.AreEqual("`Age` = @sqlinq_1", result.Where); + + Assert.AreEqual(1, result.Parameters.Count); + Assert.AreEqual(12, result.Parameters["@sqlinq_1"]); + + Assert.AreEqual(7, result.Select.Length); + Assert.AreEqual("`ID`", result.Select[0]); + Assert.AreEqual("`FirstName`", result.Select[1]); + Assert.AreEqual("`LastName`", result.Select[2]); + Assert.AreEqual("`Age`", result.Select[3]); + Assert.AreEqual("`[Is_Employed]` AS `IsEmployed`", result.Select[4]); + Assert.AreEqual("`ParentID`", result.Select[5]); + Assert.AreEqual("`Column With Spaces` AS `ColumnWithSpaces`", result.Select[6]); + } + [TestMethod] public void SQLinqTest_002() { @@ -54,6 +79,19 @@ public void SQLinqTest_002() Assert.AreEqual("Chris", result.Parameters["@sqlinq_1"]); } + [TestMethod] + public void SQLinqTest_Mysql_002() + { + var query = new SQLinq(new MySqlDialect()).Where(d => d.FirstName == "Chris"); + + var result = (SQLinqSelectResult)query.ToSQL(); + + Assert.AreEqual("`FirstName` = @sqlinq_1", result.Where); + + Assert.AreEqual(1, result.Parameters.Count); + Assert.AreEqual("Chris", result.Parameters["@sqlinq_1"]); + } + [TestMethod] public void SQLinqTest_003() { @@ -312,6 +350,22 @@ public void SQLinq_Distinct_Take_001() Assert.AreEqual("SELECT DISTINCT TOP 10 [FirstName] FROM [Person]", code); } + [TestMethod] + public void SQLinq_Mysql_Distinct_Take_001() + { + var query = from d in new SQLinq(new MySqlDialect()) + select d.FirstName; + query = query.Distinct(); + + query = query.Take(10); + + var result = query.ToSQL(); + + var code = result.ToQuery(); + + Assert.AreEqual("SELECT DISTINCT `FirstName` FROM `Person` LIMIT 10 ", code); + } + [TestMethod] public void SQLinq_Distinct_Skip_001() { @@ -329,6 +383,23 @@ orderby d.FirstName Assert.AreEqual("WITH SQLinq_data_set AS (SELECT DISTINCT [FirstName], ROW_NUMBER() OVER (ORDER BY [FirstName]) AS [SQLinq_row_number] FROM [Person]) SELECT * FROM SQLinq_data_set WHERE [SQLinq_row_number] >= 11 ORDER BY [SQLinq_row_number]", code); } + [TestMethod] + public void SQLinq_Mysql_Distinct_Skip_001() + { + var query = from d in new SQLinq(new MySqlDialect()) + orderby d.FirstName + select d.FirstName; + query = query.Distinct(); + + query = query.Skip(10); + + var result = query.ToSQL(); + + var code = result.ToQuery(); + + Assert.AreEqual($"SELECT DISTINCT `FirstName` FROM `Person` ORDER BY `FirstName` LIMIT {long.MaxValue} OFFSET 10", code); + } + [TestMethod] public void SQLinq_Distinct_SkipTake_001() { @@ -346,6 +417,23 @@ orderby d.FirstName Assert.AreEqual("WITH SQLinq_data_set AS (SELECT DISTINCT [FirstName], ROW_NUMBER() OVER (ORDER BY [FirstName]) AS [SQLinq_row_number] FROM (SELECT DISTINCT [FirstName] FROM [Person]) AS d) SELECT * FROM SQLinq_data_set WHERE [SQLinq_row_number] BETWEEN 21 AND 30", code); } + [TestMethod] + public void SQLinq_Mysql_Distinct_SkipTake_001() + { + var query = from d in new SQLinq(new MySqlDialect()) + orderby d.FirstName + select d.FirstName; + query = query.Distinct(); + + query = query.Skip(20).Take(10); + + var result = query.ToSQL(); + + var code = result.ToQuery(); + + Assert.AreEqual("SELECT DISTINCT `FirstName` FROM `Person` ORDER BY `FirstName` LIMIT 10 OFFSET 20", code); + } + #endregion #region ANONYMOUS TYPE