* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / System.Data / System.Data.Common / Key.cs
1 //\r
2 // System.Data.Common.Key.cs\r
3 //\r
4 // Author:\r
5 //   Boris Kirzner  <borisk@mainsoft.com>\r
6 //   Konstantin Triger (kostat@mainsoft.com)\r
7 //\r
8 \r
9 /*\r
10   * Copyright (c) 2002-2004 Mainsoft Corporation.\r
11   *\r
12   * Permission is hereby granted, free of charge, to any person obtaining a\r
13   * copy of this software and associated documentation files (the "Software"),\r
14   * to deal in the Software without restriction, including without limitation\r
15   * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
16   * and/or sell copies of the Software, and to permit persons to whom the\r
17   * Software is furnished to do so, subject to the following conditions:\r
18   *\r
19   * The above copyright notice and this permission notice shall be included in\r
20   * all copies or substantial portions of the Software.\r
21   *\r
22   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
23   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
24   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
25   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
26   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
27   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
28   * DEALINGS IN THE SOFTWARE.\r
29   */\r
30 \r
31 using System;\r
32 using Mono.Data.SqlExpressions;\r
33 using System.ComponentModel;\r
34 \r
35 namespace System.Data.Common\r
36 {\r
37         internal class Key\r
38         {\r
39                 #region Fields\r
40 \r
41                 DataTable _table;\r
42                 DataColumn[] _columns;\r
43                 ListSortDirection[] _sortDirection;\r
44                 DataViewRowState _rowStateFilter;\r
45                 IExpression _filter;\r
46                 //Currently IExpression.Eval does not receive DataRowVersion\r
47                 //      and always uses the _current version\r
48                 //so need a temp row for Eval calls\r
49                 DataRow _tmpRow;\r
50 \r
51                 #endregion //Fields\r
52 \r
53                 #region Constructors\r
54 \r
55                 internal Key(DataTable table,DataColumn[] columns,ListSortDirection[] sort, DataViewRowState rowState, IExpression filter)\r
56                 {\r
57                         _table = table;\r
58                         _filter = filter;\r
59                         if (_filter != null)\r
60                                 _tmpRow = _table.NewNotInitializedRow();\r
61                         _columns = columns;\r
62                         if (sort != null && sort.Length == columns.Length) {\r
63                                 _sortDirection = sort;\r
64                         }\r
65                         else {\r
66                                 _sortDirection = new ListSortDirection[columns.Length];\r
67                                 for(int i=0; i < _sortDirection.Length; i++) {\r
68                                         _sortDirection[i] = ListSortDirection.Ascending;\r
69                                 }\r
70                         }\r
71 \r
72                         if (rowState != DataViewRowState.None)\r
73                                 _rowStateFilter = rowState;\r
74                         else\r
75                                 // FIXME : what is the correct value ?\r
76                                 _rowStateFilter = DataViewRowState.CurrentRows;\r
77                 }\r
78 \r
79                 #endregion // Constructors\r
80 \r
81                 #region Properties\r
82 \r
83                 internal DataColumn[] Columns\r
84                 {\r
85                         get {\r
86                                 return _columns;\r
87                         }\r
88                 }\r
89 \r
90                 internal DataTable Table\r
91                 {\r
92                         get {\r
93                                 return _table;\r
94                         }\r
95                 }\r
96 \r
97                 ListSortDirection[] Sort \r
98                 {\r
99                         get {\r
100                                 return _sortDirection;\r
101                         }\r
102                 }\r
103 \r
104                 internal DataViewRowState RowStateFilter\r
105                 {\r
106                         get {\r
107                                 return _rowStateFilter;\r
108                         }\r
109 \r
110                         set {\r
111                                 _rowStateFilter = value;\r
112                         }\r
113                 }\r
114 \r
115                 internal bool HasFilter\r
116                 {\r
117                         get { return _filter != null; }\r
118                 }\r
119 \r
120                 #endregion // Properties\r
121 \r
122                 #region Methods\r
123 \r
124                 internal int CompareRecords(int first, int second)\r
125                 {\r
126                         if (first == second) {\r
127                                 return 0;\r
128                         }\r
129 \r
130                         for(int i = 0; i < Columns.Length; i++) {\r
131 \r
132                                 int res = Columns[i].CompareValues(first,second);\r
133 \r
134                                 if (res == 0) {\r
135                                         continue;\r
136                                 }\r
137 \r
138                                 return (Sort[i] == ListSortDirection.Ascending) ? res : -res;\r
139                         }\r
140                         return 0;\r
141                 }\r
142 \r
143                 internal int GetRecord(DataRow row)\r
144                 {\r
145                         int index = Key.GetRecord(row,_rowStateFilter);\r
146                         if (_filter == null)\r
147                                 return index;\r
148 \r
149                         if (index < 0)\r
150                                 return index;\r
151 \r
152                         return CanContain (index) ? index : -1;\r
153                 }\r
154 \r
155                 internal bool CanContain (int index)\r
156                 {\r
157                         if (_filter == null)\r
158                                 return true;\r
159 \r
160                         _tmpRow._current = index;\r
161                         return _filter.EvalBoolean(_tmpRow);\r
162                 }\r
163 \r
164                 internal bool ContainsVersion (DataRowState state, DataRowVersion version)\r
165                 {\r
166                         switch (state) {\r
167                                 case DataRowState.Unchanged:\r
168                                         if ((_rowStateFilter & DataViewRowState.Unchanged) != DataViewRowState.None)\r
169                                                 return ((version & DataRowVersion.Default) != 0);\r
170                                         break;\r
171                                 case DataRowState.Added:\r
172                                         if ((_rowStateFilter & DataViewRowState.Added) != DataViewRowState.None)\r
173                                                 return ((version & DataRowVersion.Default) != 0);\r
174                                         break;\r
175                                 case DataRowState.Deleted:\r
176                                         if ((_rowStateFilter & DataViewRowState.Deleted) != DataViewRowState.None)\r
177                                                 return (version == DataRowVersion.Original);\r
178                                         break;\r
179                                 default:\r
180                                         if ((_rowStateFilter & DataViewRowState.ModifiedCurrent) != DataViewRowState.None)\r
181                                                 return ((version & DataRowVersion.Default) != 0);\r
182                                         if ((_rowStateFilter & DataViewRowState.ModifiedOriginal) != DataViewRowState.None)\r
183                                                 return (version == DataRowVersion.Original);\r
184                                         break;\r
185                         }\r
186 \r
187                         return false;\r
188                 }\r
189 \r
190                 internal static int GetRecord(DataRow row, DataViewRowState rowStateFilter)\r
191                 {\r
192                         switch (row.RowState) {\r
193                                 case DataRowState.Unchanged: {\r
194                                         if ((rowStateFilter & DataViewRowState.Unchanged) != DataViewRowState.None)\r
195                                                 return row.Proposed >= 0 ? row.Proposed : row.Current;\r
196                                         break;\r
197                                 }\r
198                                 case DataRowState.Added: {\r
199                                         if ((rowStateFilter & DataViewRowState.Added) != DataViewRowState.None)\r
200                                                 return row.Proposed >= 0 ? row.Proposed : row.Current;\r
201                                         break;\r
202                                 }\r
203                                 case DataRowState.Deleted: {\r
204                                         if ((rowStateFilter & DataViewRowState.Deleted) != DataViewRowState.None)\r
205                                                 return row.Original;\r
206                                         break;\r
207                                 }\r
208                                 default:\r
209                                         if ((rowStateFilter & DataViewRowState.ModifiedCurrent) != DataViewRowState.None)\r
210                                                 return row.Proposed >= 0 ? row.Proposed : row.Current;\r
211                                         if ((rowStateFilter & DataViewRowState.ModifiedOriginal) != DataViewRowState.None)\r
212                                                 return row.Original;\r
213                                         break;\r
214                         }\r
215 \r
216                         return -1;\r
217                 }\r
218 \r
219                 /// <summary>\r
220                 /// Checks for key equality to parameters set given\r
221                 /// </summary>\r
222                 /// <param name="columns">Columns the key consits of. If this parameter is null, it does not affects equality check</param>\r
223                 /// <param name="sort">Sort order of columns. If this parameter is null, it does not affects equality check</param>\r
224                 /// <param name="rowState">DataViewRowState to check for.If this parameter is null, it does not affects equality check</param>\r
225                 /// <param name="unique">Indicates whenever the index managed by this key allows non-uniqie keys to appear.</param>\r
226                 /// <param name="strict">Indicates whenever unique parameter should affect the equality check.</param>\r
227                 /// <returns></returns>\r
228                 internal bool Equals(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter) \r
229                 {\r
230                         if (rowState != DataViewRowState.None && RowStateFilter != rowState) {\r
231                                 return false;\r
232                         }\r
233 \r
234                         if (_filter != null) {\r
235                                 if (!_filter.Equals (filter))\r
236                                         return false;\r
237                         }\r
238                         else if (filter != null)\r
239                                         return false;\r
240 \r
241                         if (Columns.Length != columns.Length) {\r
242                                 return false;\r
243                         }\r
244 \r
245                         if (sort != null && Sort.Length != sort.Length) {\r
246                                 return false;\r
247                         }\r
248 \r
249                         if (sort != null) {\r
250                                 for(int i=0; i < columns.Length; i++) {\r
251                                         if (Sort[i] != sort[i] || Columns[i] != columns[i]) {\r
252                                                 return false;\r
253                                         }\r
254                                 }\r
255                         }\r
256                         else {\r
257                                 for(int i=0; i < columns.Length; i++) {\r
258                                         if (Sort [i] != ListSortDirection.Ascending || Columns[i] != columns[i]) {\r
259                                                 return false;\r
260                                         }\r
261                                 }\r
262                         }\r
263                         return true;\r
264                 }\r
265 \r
266                 internal bool DependsOn (DataColumn column)\r
267                 {\r
268                         if (_filter == null)\r
269                                 return false;\r
270 \r
271                         return _filter.DependsOn (column);\r
272                 }\r
273 \r
274                 #endregion // Methods\r
275         }\r
276 }\r