diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs index bbf089be..5b9fb9dc 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs @@ -9,6 +9,44 @@ namespace FreeSql.Tests.SqlServer { public class SqlServerSelectWithTempQueryTest { + [Fact] + public void Issues1519() + { + var fsql = g.oracle; + + var query = fsql.Select() + .FromQuery(fsql.Select().WithTempQuery(e => e)) + .InnerJoin(t => t.t1.Id == t.t2.T1JoinId) + .WithTempQuery(t => new + { + t.t1.Id, + t.t1.Name, + T2Id = t.t2.Id, + T2Name = t.t1.Name, + }); + var sql = query.ToSql(); + Assert.Equal(sql, @"SELECT * +FROM ( + SELECT a.""ID"", a.""NAME"", htb.""ID"" ""T2ID"", a.""NAME"" ""T2NAME"" + FROM ""ISSUES1510T1"" a + INNER JOIN ( + SELECT a.""ID"", a.""NAME"", a.""T1JOINID"" + FROM ""ISSUES1510T2"" a ) htb ON a.""ID"" = htb.""T1JOINID"" ) a"); + query.ToList(); + + query.Page(2, 5); + sql = query.ToSql(); + Assert.Equal(sql, @"SELECT t.* FROM (SELECT a.*, ROWNUM AS ""__rownum__"" +FROM ( + SELECT a.""ID"", a.""NAME"", htb.""ID"" ""T2ID"", a.""NAME"" ""T2NAME"" + FROM ""ISSUES1510T1"" a + INNER JOIN ( + SELECT a.""ID"", a.""NAME"", a.""T1JOINID"" + FROM ""ISSUES1510T2"" a ) htb ON a.""ID"" = htb.""T1JOINID"" ) a +WHERE ROWNUM < 11) t WHERE t.""__rownum__"" > 5"); + query.ToList(); + } + [Fact] public void Issues1510() { diff --git a/FreeSql.Tests/tests.playlist b/FreeSql.Tests/tests.playlist new file mode 100644 index 00000000..a7cc0cc4 --- /dev/null +++ b/FreeSql.Tests/tests.playlist @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs index e9b1a489..5fbbf47b 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs @@ -188,6 +188,17 @@ namespace FreeSql expContext.Value.Result = $"{expContext.Value.ParsedContent["value1"]} <= {expContext.Value.ParsedContent["value2"]}"; return false; } + /// + /// value1 IS NULL + /// + /// + /// + /// + public static bool EqualIsNull(TValue value1) + { + expContext.Value.Result = $"{expContext.Value.ParsedContent["value1"]} IS NULL"; + return false; + } #endregion /// diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 8cd7ad2d..9f25ee32 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1377,6 +1377,14 @@ + + + value1 IS NULL + + + + + case when .. then .. end diff --git a/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleSelect.cs b/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleSelect.cs index 0b51424f..3fbf9b58 100644 --- a/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleSelect.cs +++ b/Providers/FreeSql.Provider.Custom/Oracle/Curd/CustomOracleSelect.cs @@ -32,11 +32,15 @@ namespace FreeSql.Custom.Oracle sbunion.Append(_select); if (_distinct) sbunion.Append("DISTINCT "); - sbunion.Append(field); - if (string.IsNullOrEmpty(_orderby) && _skip > 0) sbunion.Append(", ROWNUM AS \"__rownum__\""); - sbunion.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + + var isRownum = string.IsNullOrEmpty(_orderby) && _skip > 0; + if (isRownum && field == "*") sbunion.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sbunion.Append(field); + if (isRownum) sbunion.Append(", ROWNUM AS \"__rownum__\""); + sbunion.Append(" \r\nFROM "); + for (var a = 0; a < tbsfrom.Length; a++) { sbunion.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); diff --git a/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs b/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs index 9d07dd2d..6aa9cbb1 100644 --- a/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs +++ b/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs @@ -41,7 +41,7 @@ namespace FreeSql.Custom.SqlServer if (_distinct) sb.Append("DISTINCT "); //if (_limit > 0) sb.Append("TOP ").Append(_skip + _limit).Append(" "); //TOP 会引发 __rownum__ 无序的问题 if (_skip <= 0 && _limit > 0) sb.Append("TOP ").Append(_limit).Append(" "); - sb.Append(field); + var rownum = ""; if (_limit > 0 || _skip > 0) { @@ -57,11 +57,14 @@ namespace FreeSql.Custom.SqlServer _orderby = _groupby.Replace("GROUP BY ", "ORDER BY "); } if (_skip > 0) // 注意这个判断,大于 0 才使用 ROW_NUMBER ,否则属于第一页直接使用 TOP - sb.Append(", ROW_NUMBER() OVER(").Append(_orderby.Trim('\r', '\n', ' ')).Append(") AS __rownum__"); + rownum = $", ROW_NUMBER() OVER({_orderby.Trim('\r', '\n', ' ')}) AS __rownum__"; } - sb.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + if (string.IsNullOrEmpty(rownum) == false && field == "*") + sb.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sb.Append(field).Append(rownum); + sb.Append(" \r\nFROM "); for (var a = 0; a < tbsfrom.Length; a++) { var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs index 29d769ab..344f2c41 100644 --- a/Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs @@ -32,11 +32,14 @@ namespace FreeSql.Dameng.Curd sbunion.Append(_select); if (_distinct) sbunion.Append("DISTINCT "); - sbunion.Append(field); - if (string.IsNullOrEmpty(_orderby) && _skip > 0) sbunion.Append(", ROWNUM AS \"__rownum__\""); - sbunion.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + + var isRownum = string.IsNullOrEmpty(_orderby) && _skip > 0; + if (isRownum && field == "*") sbunion.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sbunion.Append(field); + if (isRownum) sbunion.Append(", ROWNUM AS \"__rownum__\""); + sbunion.Append(" \r\nFROM "); for (var a = 0; a < tbsfrom.Length; a++) { sbunion.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs index 7066b98b..a56c5cd5 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs @@ -32,11 +32,14 @@ namespace FreeSql.Odbc.Dameng sbunion.Append(_select); if (_distinct) sbunion.Append("DISTINCT "); - sbunion.Append(field); - if (string.IsNullOrEmpty(_orderby) && _skip > 0) sbunion.Append(", ROWNUM AS \"__rownum__\""); - sbunion.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + + var isRownum = string.IsNullOrEmpty(_orderby) && _skip > 0; + if (isRownum && field == "*") sbunion.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sbunion.Append(field); + if (isRownum) sbunion.Append(", ROWNUM AS \"__rownum__\""); + sbunion.Append(" \r\nFROM "); for (var a = 0; a < tbsfrom.Length; a++) { sbunion.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleSelect.cs b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleSelect.cs index 54dd773c..898f0c53 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleSelect.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleSelect.cs @@ -32,11 +32,14 @@ namespace FreeSql.Odbc.Oracle sbunion.Append(_select); if (_distinct) sbunion.Append("DISTINCT "); - sbunion.Append(field); - if (string.IsNullOrEmpty(_orderby) && _skip > 0) sbunion.Append(", ROWNUM AS \"__rownum__\""); - sbunion.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + + var isRownum = string.IsNullOrEmpty(_orderby) && _skip > 0; + if (isRownum && field == "*") sbunion.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sbunion.Append(field); + if (isRownum) sbunion.Append(", ROWNUM AS \"__rownum__\""); + sbunion.Append(" \r\nFROM "); for (var a = 0; a < tbsfrom.Length; a++) { sbunion.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs index 1e3bfdce..03a2b81c 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs @@ -41,7 +41,7 @@ namespace FreeSql.Odbc.SqlServer if (_distinct) sb.Append("DISTINCT "); //if (_limit > 0) sb.Append("TOP ").Append(_skip + _limit).Append(" "); //TOP 会引发 __rownum__ 无序的问题 if (_skip <= 0 && _limit > 0) sb.Append("TOP ").Append(_limit).Append(" "); - sb.Append(field); + var rownum = ""; if (_limit > 0 || _skip > 0) { @@ -57,11 +57,14 @@ namespace FreeSql.Odbc.SqlServer _orderby = _groupby.Replace("GROUP BY ", "ORDER BY "); } if (_skip > 0) // 注意这个判断,大于 0 才使用 ROW_NUMBER ,否则属于第一页直接使用 TOP - sb.Append(", ROW_NUMBER() OVER(").Append(_orderby.Trim('\r', '\n', ' ')).Append(") AS __rownum__"); + rownum = $", ROW_NUMBER() OVER({_orderby.Trim('\r', '\n', ' ')}) AS __rownum__"; } - sb.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + if (string.IsNullOrEmpty(rownum) == false && field == "*") + sb.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sb.Append(field).Append(rownum); + sb.Append(" \r\nFROM "); for (var a = 0; a < tbsfrom.Length; a++) { var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs index 636d961b..f4db61dd 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs @@ -32,11 +32,15 @@ namespace FreeSql.Oracle.Curd sbunion.Append(_select); if (_distinct) sbunion.Append("DISTINCT "); - sbunion.Append(field); - if (string.IsNullOrEmpty(_orderby) && _skip > 0) sbunion.Append(", ROWNUM AS \"__rownum__\""); - sbunion.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + + var isRownum = string.IsNullOrEmpty(_orderby) && _skip > 0; + if (isRownum && field == "*") sbunion.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sbunion.Append(field); + if (isRownum) sbunion.Append(", ROWNUM AS \"__rownum__\""); + sbunion.Append(" \r\nFROM "); + for (var a = 0; a < tbsfrom.Length; a++) { sbunion.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs index ac66d414..b19c51de 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs @@ -41,7 +41,7 @@ namespace FreeSql.SqlServer.Curd if (_distinct) sb.Append("DISTINCT "); //if (_limit > 0) sb.Append("TOP ").Append(_skip + _limit).Append(" "); //TOP 会引发 __rownum__ 无序的问题 if (_skip <= 0 && _limit > 0) sb.Append("TOP ").Append(_limit).Append(" "); - sb.Append(field); + var rownum = ""; if (_limit > 0 || _skip > 0) { @@ -57,11 +57,14 @@ namespace FreeSql.SqlServer.Curd _orderby = _groupby.Replace("GROUP BY ", "ORDER BY "); } if (_skip > 0) // 注意这个判断,大于 0 才使用 ROW_NUMBER ,否则属于第一页直接使用 TOP - sb.Append(", ROW_NUMBER() OVER(").Append(_orderby.Trim('\r', '\n', ' ')).Append(") AS __rownum__"); + rownum = $", ROW_NUMBER() OVER({_orderby.Trim('\r', '\n', ' ')}) AS __rownum__"; } - sb.Append(" \r\nFROM "); var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + if (string.IsNullOrEmpty(rownum) == false && field == "*") + sb.Append(tbsfrom[0].Alias).Append("."); //#1519 bug + sb.Append(field).Append(rownum); + sb.Append(" \r\nFROM "); for (var a = 0; a < tbsfrom.Length; a++) { var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule);