merging the Mainsoft branch to the trunk
[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                         }\r
75                         else {\r
76                                 // FIXME : what is the correct value ?\r
77                                 _rowStateFilter = DataViewRowState.CurrentRows;\r
78                         }\r
79                 }\r
80 \r
81                 #endregion // Constructors\r
82 \r
83                 #region Properties\r
84 \r
85                 internal DataColumn[] Columns\r
86                 {\r
87                         get {\r
88                                 return _columns;\r
89                         }\r
90                 }\r
91 \r
92                 internal DataTable Table\r
93                 {\r
94                         get {\r
95                                 return _table;\r
96                         }\r
97                 }\r
98 \r
99                 ListSortDirection[] Sort \r
100                 {\r
101                         get {\r
102                                 return _sortDirection;\r
103                         }\r
104                 }\r
105 \r
106                 internal DataViewRowState RowStateFilter\r
107                 {\r
108                         get {\r
109                                 return _rowStateFilter;\r
110                         }\r
111 \r
112                         set {\r
113                                 _rowStateFilter = value;\r
114                         }\r
115                 }\r
116 \r
117                 #endregion // Properties\r
118 \r
119                 #region Methods\r
120 \r
121                 internal int CompareRecords(int first, int second)\r
122                 {\r
123                         if (first == second) {\r
124                                 return 0;\r
125                         }\r
126 \r
127                         for(int i = 0; i < Columns.Length; i++) {\r
128 \r
129                                 int res = Columns[i].CompareValues(first,second);\r
130 \r
131                                 if (res == 0) {\r
132                                         continue;\r
133                                 }\r
134 \r
135                                 return (Sort[i] == ListSortDirection.Ascending) ? res : -res;\r
136                         }\r
137                         return 0;\r
138                 }\r
139 \r
140                 internal int GetRecord(DataRow row)\r
141                 {\r
142                         int index = Key.GetRecord(row,_rowStateFilter);\r
143                         if (_filter == null)\r
144                                 return index;\r
145 \r
146                         if (index < 0)\r
147                                 return index;\r
148 \r
149                         _tmpRow._current = index;\r
150                         return _filter.EvalBoolean(_tmpRow) ? index : -1;\r
151                 }\r
152 \r
153                 internal static int GetRecord(DataRow row, DataViewRowState rowStateFilter)\r
154                 {\r
155 \r
156                         if (row.Original == row.Current) {\r
157                                  if ((rowStateFilter & DataViewRowState.Unchanged) != DataViewRowState.None) {\r
158                                          return row.Current;\r
159                                  }\r
160                         }\r
161                         else if (row.Original == -1) {\r
162                                   if ((rowStateFilter & DataViewRowState.Added) != DataViewRowState.None) {\r
163                                         return row.Current;\r
164                                   }\r
165                         }\r
166                         else if (row.Current == -1) {\r
167                                      if ((rowStateFilter & DataViewRowState.Deleted) != DataViewRowState.None) {\r
168                                                 return row.Original;\r
169                                          }\r
170                         }\r
171                         else if ((rowStateFilter & DataViewRowState.ModifiedCurrent) != DataViewRowState.None) {\r
172                                 return row.Current;\r
173                         }\r
174                         else if ((rowStateFilter & DataViewRowState.ModifiedOriginal) != DataViewRowState.None) {\r
175                                 return row.Original;\r
176                         }\r
177 \r
178             return -1;\r
179                 }\r
180 \r
181                 /// <summary>\r
182                 /// Checks for key equality to parameters set given\r
183                 /// </summary>\r
184                 /// <param name="columns">Columns the key consits of. If this parameter is null, it does not affects equality check</param>\r
185                 /// <param name="sort">Sort order of columns. If this parameter is null, it does not affects equality check</param>\r
186                 /// <param name="rowState">DataViewRowState to check for.If this parameter is null, it does not affects equality check</param>\r
187                 /// <param name="unique">Indicates whenever the index managed by this key allows non-uniqie keys to appear.</param>\r
188                 /// <param name="strict">Indicates whenever unique parameter should affect the equality check.</param>\r
189                 /// <returns></returns>\r
190                 internal bool Equals(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter) \r
191                 {\r
192                         if (rowState != DataViewRowState.None && RowStateFilter != rowState) {\r
193                                 return false;\r
194                         }\r
195 \r
196                         if (_filter != filter)\r
197                                 return false;\r
198 \r
199                         if (Columns.Length != columns.Length) {\r
200                                 return false;\r
201                         }\r
202 \r
203                         if (sort != null && Sort.Length != sort.Length) {\r
204                                 return false;\r
205                         }\r
206 \r
207                         if (sort != null) {\r
208                                 for(int i=0; i < columns.Length; i++) {\r
209                                         if (Sort[i] != sort[i] || Columns[i] != columns[i]) {\r
210                                                 return false;\r
211                                         }\r
212                                 }\r
213                         }\r
214                         else {\r
215                                 for(int i=0; i < columns.Length; i++) {\r
216                                         if (Columns[i] != columns[i]) {\r
217                                                 return false;\r
218                                         }\r
219                                 }\r
220                         }\r
221                         return true;\r
222                 }\r
223 \r
224                 #endregion // Methods\r
225         }\r
226 }\r