SqlRemoveConstantOrderBy.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Data;
  6. namespace System.Data.Linq.SqlClient {
  7. using System.Data.Linq;
  8. /// <summary>
  9. /// SQL doesn't allow constants in ORDER BY.
  10. ///
  11. /// Worse, an integer constant greater than 0 is treated as ORDER BY ProjectionColumn[i] so the results
  12. /// can be unexpected.
  13. ///
  14. /// The LINQ semantic for OrderBy(o=>constant) is for it to have no effect on the ordering. We enforce
  15. /// that semantic here by removing all constant columns from OrderBy.
  16. /// </summary>
  17. internal class SqlRemoveConstantOrderBy {
  18. private class Visitor : SqlVisitor {
  19. internal override SqlSelect VisitSelect(SqlSelect select) {
  20. int i = 0;
  21. List<SqlOrderExpression> orders = select.OrderBy;
  22. while (i < orders.Count) {
  23. SqlExpression expr = orders[i].Expression;
  24. while (expr.NodeType == SqlNodeType.DiscriminatedType) {
  25. expr = ((SqlDiscriminatedType)expr).Discriminator;
  26. }
  27. switch (expr.NodeType) {
  28. case SqlNodeType.Value:
  29. case SqlNodeType.Parameter:
  30. orders.RemoveAt(i);
  31. break;
  32. default:
  33. ++i;
  34. break;
  35. }
  36. }
  37. return base.VisitSelect(select);
  38. }
  39. }
  40. /// <summary>
  41. /// Remove relative constants from OrderBy.
  42. /// </summary>
  43. internal static SqlNode Remove(SqlNode node) {
  44. return new Visitor().Visit(node);
  45. }
  46. }
  47. }