SmiMetaDataProperty.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SmiMetaData.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. //------------------------------------------------------------------------------
  8. namespace Microsoft.SqlServer.Server {
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Data;
  12. using System.Data.Common;
  13. using System.Data.SqlClient;
  14. using System.Diagnostics;
  15. using System.Globalization;
  16. // SmiMetaDataProperty defines an extended, optional property to be used on the SmiMetaData class
  17. // This approach to adding properties is added combat the growing number of sparsely-used properties
  18. // that are specially handled on the base classes
  19. internal enum SmiPropertySelector {
  20. DefaultFields = 0x0,
  21. SortOrder = 0x1,
  22. UniqueKey = 0x2,
  23. }
  24. // Simple collection for properties. Could extend to IDictionary support if needed in future.
  25. internal class SmiMetaDataPropertyCollection {
  26. private const int SelectorCount = 3; // number of elements in SmiPropertySelector
  27. private SmiMetaDataProperty[] _properties;
  28. private bool _isReadOnly;
  29. internal static readonly SmiMetaDataPropertyCollection EmptyInstance;
  30. // Singleton empty instances to ensure each property is always non-null
  31. private static readonly SmiDefaultFieldsProperty __emptyDefaultFields = new SmiDefaultFieldsProperty(new List<bool>());
  32. private static readonly SmiOrderProperty __emptySortOrder = new SmiOrderProperty(new List<SmiOrderProperty.SmiColumnOrder>());
  33. private static readonly SmiUniqueKeyProperty __emptyUniqueKey = new SmiUniqueKeyProperty(new List<bool>());
  34. static SmiMetaDataPropertyCollection() {
  35. EmptyInstance = new SmiMetaDataPropertyCollection();
  36. EmptyInstance.SetReadOnly();
  37. }
  38. internal SmiMetaDataPropertyCollection() {
  39. _properties = new SmiMetaDataProperty[SelectorCount];
  40. _isReadOnly = false;
  41. _properties[(int)SmiPropertySelector.DefaultFields] = __emptyDefaultFields;
  42. _properties[(int)SmiPropertySelector.SortOrder] = __emptySortOrder;
  43. _properties[(int)SmiPropertySelector.UniqueKey] = __emptyUniqueKey;
  44. }
  45. internal SmiMetaDataProperty this[SmiPropertySelector key] {
  46. get {
  47. return _properties[(int)key];
  48. }
  49. set {
  50. if (null == value) {
  51. throw ADP.InternalError(ADP.InternalErrorCode.InvalidSmiCall);
  52. }
  53. EnsureWritable();
  54. _properties[(int)key] = value;
  55. }
  56. }
  57. internal bool IsReadOnly {
  58. get {
  59. return _isReadOnly;
  60. }
  61. }
  62. internal IEnumerable<SmiMetaDataProperty> Values {
  63. get {
  64. return new List<SmiMetaDataProperty>(_properties);
  65. }
  66. }
  67. // Allow switching to read only, but not back.
  68. internal void SetReadOnly() {
  69. _isReadOnly = true;
  70. }
  71. private void EnsureWritable() {
  72. if (IsReadOnly) {
  73. throw System.Data.Common.ADP.InternalError(System.Data.Common.ADP.InternalErrorCode.InvalidSmiCall);
  74. }
  75. }
  76. }
  77. // Base class for properties
  78. internal abstract class SmiMetaDataProperty {
  79. internal abstract string TraceString();
  80. }
  81. // Property defining a list of column ordinals that define a unique key
  82. internal class SmiUniqueKeyProperty : SmiMetaDataProperty {
  83. private IList<bool> _columns;
  84. internal SmiUniqueKeyProperty(IList<bool> columnIsKey) {
  85. _columns = new List<bool>(columnIsKey).AsReadOnly();
  86. }
  87. // indexed by column ordinal indicating for each column whether it is key or not
  88. internal bool this[int ordinal] {
  89. get {
  90. if (_columns.Count <= ordinal) {
  91. return false;
  92. }
  93. else {
  94. return _columns[ordinal];
  95. }
  96. }
  97. }
  98. [Conditional("DEBUG")]
  99. internal void CheckCount(int countToMatch) {
  100. Debug.Assert(0 == _columns.Count || countToMatch == _columns.Count,
  101. "SmiDefaultFieldsProperty.CheckCount: DefaultFieldsProperty size (" + _columns.Count +
  102. ") not equal to checked size (" + countToMatch + ")" );
  103. }
  104. internal override string TraceString() {
  105. string returnValue = "UniqueKey(";
  106. bool delimit = false;
  107. for (int columnOrd = 0; columnOrd < _columns.Count; columnOrd++) {
  108. if (delimit) {
  109. returnValue += ",";
  110. }
  111. else {
  112. delimit = true;
  113. }
  114. if (_columns[columnOrd]) {
  115. returnValue += columnOrd.ToString(CultureInfo.InvariantCulture);
  116. }
  117. }
  118. returnValue += ")";
  119. return returnValue;
  120. }
  121. }
  122. // Property defining a sort order for a set of columns (by ordinal and ASC/DESC).
  123. internal class SmiOrderProperty : SmiMetaDataProperty {
  124. internal struct SmiColumnOrder {
  125. internal int SortOrdinal;
  126. internal SortOrder Order;
  127. internal string TraceString() {
  128. return String.Format(CultureInfo.InvariantCulture, "{0} {1}", SortOrdinal, Order);
  129. }
  130. }
  131. private IList<SmiColumnOrder> _columns;
  132. internal SmiOrderProperty(IList<SmiColumnOrder> columnOrders) {
  133. _columns = new List<SmiColumnOrder>(columnOrders).AsReadOnly();
  134. }
  135. // Readonly list of the columnorder instances making up the sort order
  136. // order in list indicates precedence
  137. internal SmiColumnOrder this[int ordinal] {
  138. get {
  139. if (_columns.Count <= ordinal) {
  140. SmiColumnOrder order = new SmiColumnOrder();
  141. order.Order = SortOrder.Unspecified;
  142. order.SortOrdinal = -1;
  143. return order;
  144. }
  145. else {
  146. return _columns[ordinal];
  147. }
  148. }
  149. }
  150. [Conditional("DEBUG")]
  151. internal void CheckCount(int countToMatch) {
  152. Debug.Assert(0 == _columns.Count || countToMatch == _columns.Count,
  153. "SmiDefaultFieldsProperty.CheckCount: DefaultFieldsProperty size (" + _columns.Count +
  154. ") not equal to checked size (" + countToMatch + ")" );
  155. }
  156. internal override string TraceString() {
  157. string returnValue = "SortOrder(";
  158. bool delimit = false;
  159. foreach(SmiColumnOrder columnOrd in _columns) {
  160. if (delimit) {
  161. returnValue += ",";
  162. }
  163. else {
  164. delimit = true;
  165. }
  166. if (System.Data.SqlClient.SortOrder.Unspecified != columnOrd.Order) {
  167. returnValue += columnOrd.TraceString();
  168. }
  169. }
  170. returnValue += ")";
  171. return returnValue;
  172. }
  173. }
  174. // property defining inheritance relationship(s)
  175. internal class SmiDefaultFieldsProperty : SmiMetaDataProperty {
  176. #region private fields
  177. private IList<bool> _defaults;
  178. #endregion
  179. #region internal interface
  180. internal SmiDefaultFieldsProperty(IList<bool> defaultFields) {
  181. _defaults = new List<bool>(defaultFields).AsReadOnly();
  182. }
  183. internal bool this[int ordinal] {
  184. get {
  185. if (_defaults.Count <= ordinal) {
  186. return false;
  187. }
  188. else {
  189. return _defaults[ordinal];
  190. }
  191. }
  192. }
  193. [Conditional("DEBUG")]
  194. internal void CheckCount(int countToMatch) {
  195. Debug.Assert(0 == _defaults.Count || countToMatch == _defaults.Count,
  196. "SmiDefaultFieldsProperty.CheckCount: DefaultFieldsProperty size (" + _defaults.Count +
  197. ") not equal to checked size (" + countToMatch + ")" );
  198. }
  199. internal override string TraceString() {
  200. string returnValue = "DefaultFields(";
  201. bool delimit = false;
  202. for(int columnOrd = 0; columnOrd < _defaults.Count; columnOrd++) {
  203. if (delimit) {
  204. returnValue += ",";
  205. }
  206. else {
  207. delimit = true;
  208. }
  209. if (_defaults[columnOrd]) {
  210. returnValue += columnOrd;
  211. }
  212. }
  213. returnValue += ")";
  214. return returnValue;
  215. }
  216. #endregion
  217. }
  218. }