PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/referencesource/System.Data/System/Data/Filter/NameNode.cs

https://github.com/kumpera/mono
C# | 189 lines | 148 code | 26 blank | 15 comment | 34 complexity | fc8c99070da9e58c4bc954efcf212fb3 MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0, Unlicense
  1. //------------------------------------------------------------------------------
  2. // <copyright file="NameNode.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">Microsoft</owner>
  6. // <owner current="true" primary="false">Microsoft</owner>
  7. // <owner current="false" primary="false">Microsoft</owner>
  8. //------------------------------------------------------------------------------
  9. namespace System.Data {
  10. using System;
  11. using System.ComponentModel;
  12. using System.Collections.Generic;
  13. using System.Diagnostics;
  14. using System.Globalization;
  15. internal sealed class NameNode : ExpressionNode {
  16. internal char open = '\0';
  17. internal char close = '\0';
  18. internal string name;
  19. internal bool found;
  20. internal bool type = false;
  21. internal DataColumn column;
  22. internal NameNode(DataTable table, char[] text, int start, int pos) : base(table) {
  23. this.name = ParseName(text, start, pos);
  24. }
  25. internal NameNode(DataTable table, string name) : base(table) {
  26. this.name = name;
  27. }
  28. internal override bool IsSqlColumn{
  29. get{
  30. return column.IsSqlType;
  31. }
  32. }
  33. internal override void Bind(DataTable table, List<DataColumn> list) {
  34. BindTable(table);
  35. if (table == null)
  36. throw ExprException.UnboundName(name);
  37. try {
  38. this.column = table.Columns[name];
  39. }
  40. catch (Exception e) {
  41. found = false;
  42. //
  43. if (!Common.ADP.IsCatchableExceptionType(e)) {
  44. throw;
  45. }
  46. throw ExprException.UnboundName(name);
  47. }
  48. if (column == null)
  49. throw ExprException.UnboundName(name);
  50. name = column.ColumnName;
  51. found = true;
  52. // add column to the dependency list, do not add duplicate columns
  53. Debug.Assert(column != null, "Failed to bind column " + name);
  54. int i;
  55. for (i = 0; i < list.Count; i++) {
  56. // walk the list, check if the current column already on the list
  57. DataColumn dataColumn = list[i];
  58. if (column == dataColumn) {
  59. break;
  60. }
  61. }
  62. if (i >= list.Count) {
  63. list.Add(column);
  64. }
  65. }
  66. internal override object Eval() {
  67. // can not eval column without ROW value;
  68. throw ExprException.EvalNoContext();
  69. }
  70. internal override object Eval(DataRow row, DataRowVersion version) {
  71. if (!found) {
  72. throw ExprException.UnboundName(name);
  73. }
  74. if (row == null) {
  75. if(IsTableConstant()) // this column is TableConstant Aggregate Function
  76. return column.DataExpression.Evaluate();
  77. else {
  78. throw ExprException.UnboundName(name);
  79. }
  80. }
  81. return column[row.GetRecordFromVersion(version)];
  82. }
  83. internal override object Eval(int[] records) {
  84. throw ExprException.ComputeNotAggregate(this.ToString());
  85. }
  86. internal override bool IsConstant() {
  87. return false;
  88. }
  89. internal override bool IsTableConstant() {
  90. if (column != null && column.Computed) {
  91. return this.column.DataExpression.IsTableAggregate();
  92. }
  93. return false;
  94. }
  95. internal override bool HasLocalAggregate() {
  96. if (column != null && column.Computed) {
  97. return this.column.DataExpression.HasLocalAggregate();
  98. }
  99. return false;
  100. }
  101. internal override bool HasRemoteAggregate() {
  102. if (column != null && column.Computed) {
  103. return this.column.DataExpression.HasRemoteAggregate();
  104. }
  105. return false;
  106. }
  107. internal override bool DependsOn(DataColumn column) {
  108. if (this.column == column)
  109. return true;
  110. if (this.column.Computed) {
  111. return this.column.DataExpression.DependsOn(column);
  112. }
  113. return false;
  114. }
  115. internal override ExpressionNode Optimize() {
  116. return this;
  117. }
  118. /// <devdoc>
  119. /// Parses given name and checks it validity
  120. /// </devdoc>
  121. internal static string ParseName(char[] text, int start, int pos) {
  122. char esc = '\0';
  123. string charsToEscape = "";
  124. int saveStart = start;
  125. int savePos = pos;
  126. if (text[start] == '`') {
  127. Debug.Assert(text[checked((int)pos-1)] == '`', "Invalid identifyer bracketing, pos = " + pos.ToString(CultureInfo.InvariantCulture) + ", end = " + text[checked((int)pos-1)].ToString(CultureInfo.InvariantCulture));
  128. start = checked((int)start+1);
  129. pos = checked((int)pos-1);
  130. esc = '\\';
  131. charsToEscape = "`";
  132. }
  133. else if (text[start] == '[') {
  134. Debug.Assert(text[checked((int)pos-1)] == ']', "Invalid identifyer bracketing of name " + new string(text, start, pos-start) + " pos = " + pos.ToString(CultureInfo.InvariantCulture) + ", end = " + text[checked((int)pos-1)].ToString(CultureInfo.InvariantCulture));
  135. start = checked((int)start+1);
  136. pos = checked((int)pos-1);
  137. esc = '\\';
  138. charsToEscape = "]\\";
  139. }
  140. if (esc != '\0') {
  141. // scan the name in search for the ESC
  142. int posEcho = start;
  143. for (int i = start; i < pos; i++) {
  144. if (text[i] == esc) {
  145. if (i+1 < pos && charsToEscape.IndexOf(text[i+1]) >= 0) {
  146. i++;
  147. }
  148. }
  149. text[posEcho] = text[i];
  150. posEcho++;
  151. }
  152. pos = posEcho;
  153. }
  154. if (pos == start)
  155. throw ExprException.InvalidName(new string(text, saveStart, savePos - saveStart));
  156. return new string(text, start, pos - start);
  157. }
  158. }
  159. }