importing messaging-2008 branch to trunk [continued]
[mono.git] / mcs / class / System.Data / System.Data / ExpressionElement.cs
1 //\r
2 // System.Data.ExpressionElement \r
3 //\r
4 // Author:\r
5 //   Ville Palo <vi64pa@kolumbus.fi>\r
6 //\r
7 // Copyright (C) Ville Palo, 2003\r
8 //\r
9 // TODO: - Some functionelements and aggregates.\r
10 //       - New parsing style.\r
11 //       - Exceptions\r
12 //\r
13 \r
14 using System;\r
15 using System.Data;\r
16 using System.Reflection;\r
17 \r
18 using System.Collections;\r
19 using System.Text;\r
20 \r
21 namespace System.Data\r
22 {\r
23 #if false\r
24         /// <summary>\r
25         /// The main element which includes whole expression\r
26         /// </summary>\r
27         internal class ExpressionMainElement : ExpressionElement\r
28         {\r
29                 \r
30                 \r
31 \r
32                 public ExpressionMainElement (string s)\r
33                 {\r
34                         s = ExpressionElement.ValidateExpression (s);\r
35                         ParseExpression (s);\r
36                 }\r
37                 \r
38                 public override bool Test (DataRow Row) \r
39                 {\r
40 \r
41                         foreach (ExpressionElement El in Elements) \r
42                         {\r
43                                 if (!El.Test (Row))\r
44                                         return false;\r
45                         }\r
46                         \r
47                         return true;\r
48                 }\r
49 \r
50                 \r
51         }\r
52 \r
53         //\r
54         // O_P_E_R_A_T_O_R_S\r
55         //\r
56 \r
57         /// <summary>\r
58         ///  Class for =\r
59         /// </summary>\r
60         internal class ExpressionEquals : ExpressionElement\r
61         {       \r
62 \r
63                 public ExpressionEquals (string exp1, string exp2) \r
64                 {       \r
65                         this.exp1 = exp1;\r
66                         this.exp2 = exp2;\r
67                         ParseExpression (exp1);\r
68                         ParseExpression (exp2);\r
69                 }\r
70 \r
71                 public override bool Test (DataRow Row) \r
72                 {\r
73                         \r
74                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
75                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
76 \r
77                         return ExpressionElement.Compare (E1, E2, Row) == 0;\r
78                 }\r
79         }\r
80 \r
81         /// <summary>\r
82         ///  Class for <\r
83         /// </summary>\r
84         internal class ExpressionLessThan : ExpressionElement\r
85         {       \r
86 \r
87                 public ExpressionLessThan (string exp1, string exp2) \r
88                 {       \r
89                         this.exp1 = exp1;\r
90                         this.exp2 = exp2;\r
91                         ParseExpression (exp1);\r
92                         ParseExpression (exp2);\r
93                 }\r
94 \r
95                 public override bool Test (DataRow Row) \r
96                 {\r
97                                                                 \r
98                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
99                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
100                                            \r
101                         return ExpressionElement.Compare (E1, E2, Row) < 0;\r
102                 }\r
103         }\r
104 \r
105         /// <summary>\r
106         ///  Class for <=\r
107         /// </summary>\r
108         internal class ExpressionLessThanOrEqual : ExpressionElement\r
109         {       \r
110 \r
111                 public ExpressionLessThanOrEqual (string exp1, string exp2) \r
112                 {       \r
113                         this.exp1 = exp1;\r
114                         this.exp2 = exp2;\r
115                         ParseExpression (exp1);\r
116                         ParseExpression (exp2);\r
117                 }\r
118 \r
119                 public override bool Test (DataRow Row) \r
120                 {\r
121 \r
122                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
123                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
124 \r
125                         return ExpressionElement.Compare (E1, E2, Row) <= 0;\r
126                 }\r
127         }\r
128 \r
129         /// <summary>\r
130         ///  Class for >\r
131         /// </summary>\r
132         internal class ExpressionGreaterThan : ExpressionElement\r
133         {       \r
134 \r
135                 public ExpressionGreaterThan (string exp1, string exp2) \r
136                 {       \r
137                         this.exp1 = exp1;\r
138                         this.exp2 = exp2;\r
139                         ParseExpression (exp1);\r
140                         ParseExpression (exp2);\r
141                 }\r
142 \r
143                 public override bool Test (DataRow Row) \r
144                 {\r
145                         \r
146                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
147                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
148 \r
149                         return ExpressionElement.Compare (E1, E2, Row) > 0;\r
150                 }\r
151         }\r
152 \r
153         /// <summary>\r
154         ///  Class for >=\r
155         /// </summary>\r
156         internal class ExpressionGreaterThanOrEqual : ExpressionElement\r
157         {       \r
158 \r
159                 public ExpressionGreaterThanOrEqual (string exp1, string exp2) \r
160                 {       \r
161                         this.exp1 = exp1;\r
162                         this.exp2 = exp2;\r
163                         ParseExpression (exp1);\r
164                         ParseExpression (exp2);\r
165                 }\r
166 \r
167                 public override bool Test (DataRow Row) \r
168                 {\r
169 \r
170                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
171                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
172 \r
173                         return ExpressionElement.Compare (E1, E2, Row) >= 0;\r
174                 }\r
175         }\r
176 \r
177         /// <summary>\r
178         ///  Class for <>\r
179         /// </summary>\r
180         internal class ExpressionUnequals : ExpressionElement\r
181         {       \r
182 \r
183                 public ExpressionUnequals (string exp1, string exp2) \r
184                 {       \r
185                         this.exp1 = exp1;\r
186                         this.exp2 = exp2;\r
187                         ParseExpression (exp1);\r
188                         ParseExpression (exp2);\r
189                 }\r
190 \r
191                 public override bool Test (DataRow Row) \r
192                 {\r
193                         \r
194                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
195                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
196 \r
197                         return ExpressionElement.Compare (E1, E2, Row) != 0;\r
198                 }\r
199         }\r
200 \r
201 \r
202         /// <summary>\r
203         ///  Class for LIKE-operator\r
204         /// </summary>\r
205         internal class ExpressionLike : ExpressionElement\r
206         {       \r
207 \r
208                 public ExpressionLike (string exp1, string exp2) \r
209                 {\r
210                         ParseExpression (exp1);\r
211                         ParseExpression (exp2);\r
212                 }\r
213 \r
214                 public override bool Test (DataRow Row) \r
215                 {\r
216 \r
217                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
218                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
219                         object value1 = E1.Result (Row);\r
220                         object value2 = E2.Result (Row);\r
221                         \r
222                         if (value1.GetType () != typeof (string) || value2.GetType () != typeof (string))\r
223                                 throw new Exception (); // TODO: what exception\r
224                         \r
225                         string operand1 = value1.ToString ();\r
226                         string operand2 = value2.ToString ();\r
227 \r
228                         // find out is there wildcards like * or %.\r
229                         while (operand2.EndsWith ("*") || operand2.EndsWith ("%"))                             \r
230                                 operand2 = operand2.Remove (operand2.Length - 1, 1);\r
231                         while (operand2.StartsWith ("*") || operand2.StartsWith ("%"))\r
232                                 operand2 = operand2.Remove (0, 1);\r
233 \r
234                         int oldIndex = 0;\r
235                         int indexOf = -1;\r
236 \r
237                         indexOf = operand2.IndexOf ("*");\r
238                         while (indexOf != -1) \r
239                         {\r
240 \r
241                                 oldIndex = indexOf + 1;\r
242                                 if (operand2 [indexOf + 1] != ']' || operand2 [indexOf - 1] != '[')\r
243                                         throw new EvaluateException ("Error in Like operator: ther string pattern " + operand1 + " is invalid");\r
244                                 else \r
245                                 {\r
246                                         operand2 = operand2.Remove (indexOf + 1, 1);\r
247                                         operand2 = operand2.Remove (indexOf -1, 1);\r
248                                         oldIndex--;\r
249                                 }\r
250                                         \r
251                                 indexOf = operand2.IndexOf ("*", oldIndex);\r
252                         }\r
253 \r
254                         oldIndex = 0;\r
255                         indexOf = operand2.IndexOf ("%");\r
256                         while (indexOf != -1) \r
257                         {\r
258 \r
259                                 oldIndex = indexOf + 1;\r
260                                 \r
261                                 if (operand2 [indexOf + 1] != ']' || operand2 [indexOf - 1] != '[')\r
262                                         throw new EvaluateException ("Error in Like operator: ther string pattern " + operand2 + " is invalid");\r
263                                 else \r
264                                 {\r
265                                         operand2 = operand2.Remove (indexOf + 1, 1);\r
266                                         operand2 = operand2.Remove (indexOf -1, 1);                                     \r
267                                         oldIndex--;\r
268                                 }\r
269 \r
270                                 indexOf = operand2.IndexOf ("%", oldIndex);\r
271                         }\r
272 \r
273                         int len2 = operand2.Length;\r
274                         int startIndex = 0;\r
275                         while ((startIndex + len2) <= operand1.Length) \r
276                         {\r
277                                 if (String.Compare (operand1.Substring (startIndex, len2), operand2, !Row.Table.CaseSensitive) == 0)\r
278                                         return true;\r
279                                 startIndex++;\r
280                         }\r
281 \r
282                         return false;\r
283                 }\r
284         }\r
285 \r
286 \r
287         /// <summary>\r
288         ///  Class for OR\r
289         /// </summary>\r
290         internal class ExpressionOr : ExpressionElement\r
291         {                               \r
292                 public ExpressionOr (string exp1, string exp2)\r
293                 {\r
294                         ParseExpression (exp1);\r
295                         ParseExpression (exp2);\r
296                 }\r
297 \r
298                 public override bool Test (DataRow Row) \r
299                 {                       \r
300                         foreach (ExpressionElement El in Elements) \r
301                         {\r
302                                 if (El.Test (Row))\r
303                                         return true;\r
304                         }\r
305                         \r
306                         return false;\r
307                 }                               \r
308         }\r
309                 \r
310         /// <summary>\r
311         ///  Class for AND\r
312         /// </summary>\r
313         internal class ExpressionAnd : ExpressionElement\r
314         {                               \r
315                 public ExpressionAnd (string exp1, string exp2)\r
316                 {\r
317                         ParseExpression (exp1);\r
318                         ParseExpression (exp2);\r
319                 }\r
320                \r
321                 public override object Result (DataRow Row) \r
322                 {\r
323                         \r
324                         return Test(Row);\r
325                 }\r
326 \r
327                 public override bool Test (DataRow Row) \r
328                 {\r
329                         foreach (ExpressionElement El in Elements) \r
330                         {\r
331                                 if (!El.Test (Row))\r
332                                         return false;\r
333                         }\r
334                         \r
335                         return true;\r
336                 }                               \r
337         }\r
338 \r
339 \r
340         //\r
341         // A_R_I_T_H_M_E_T_I_C  O_P_E_R_A_T_O_R_S\r
342         //\r
343 \r
344         /// <summary>\r
345         ///  Class for +\r
346         /// </summary>\r
347         internal class ExpressionAddition : ExpressionElement\r
348         {\r
349                 public ExpressionAddition (string exp1, string exp2)\r
350                 {                       \r
351                         this.exp1 = exp1;\r
352                         this.exp2 = exp2;\r
353                         ParseExpression (exp1);\r
354                         ParseExpression (exp2);\r
355                 }\r
356                 \r
357                 public override Type ResultType (DataRow Row)\r
358                 {\r
359                         Type ResultType = typeof (string);\r
360                         ExpressionElement exp1Temp = ((ExpressionElement)Elements [0]);\r
361                         ExpressionElement exp2Temp = ((ExpressionElement)Elements [1]);\r
362 \r
363                         if (exp1Temp.ResultType (Row) == typeof (string) || exp2Temp.ResultType (Row) == typeof (string))\r
364                                 ResultType = typeof (string);\r
365 \r
366                         else if (exp1Temp.ResultType (Row) == typeof (long) || exp2Temp.ResultType (Row) == typeof (long))\r
367                                 ResultType = typeof (long);\r
368 \r
369                         else if (exp1Temp.ResultType (Row) == typeof (int) || exp2Temp.ResultType (Row) == typeof (int))\r
370                                 ResultType = typeof (int);\r
371 \r
372                         return ResultType;\r
373                 }\r
374 \r
375                 public override object Result (DataRow Row) \r
376                 {\r
377                         return CalculateResult (Row);\r
378                 }\r
379                 \r
380                 protected override object Calculate (object value1, object value2, Type TempType) \r
381                 {\r
382                         object Result = null;                   \r
383 \r
384                         if (TempType == typeof (string))\r
385                                 Result = (string)value1 + (string)value2;\r
386                         else if (TempType == typeof (long))\r
387                                 Result = (long)value1 + (long)value2;\r
388                         else if (TempType == typeof (int))\r
389                                 Result = (int)value1 + (int)value2;\r
390                         else if (TempType == typeof (short))\r
391                                 Result = (short)value1 + (short)value2;\r
392                         else if (TempType == typeof (ulong))\r
393                                 Result = (ulong)value1 + (ulong)value2;\r
394                         else if (TempType == typeof (uint))\r
395                                 Result = (uint)value1 + (uint)value2;\r
396                         else if (TempType == typeof (ushort))\r
397                                 Result = (ushort)value1 + (ushort)value2;\r
398                         else if (TempType == typeof (byte))\r
399                                 Result = (byte)value1 + (byte)value2;\r
400                         else if (TempType == typeof (sbyte))\r
401                                 Result = (sbyte)value1 + (sbyte)value2;\r
402                                 // FIXME:\r
403                                 //else if (TempType == typeof (bool))\r
404                                 //      Result = (bool)value1 + (bool)value2;\r
405                         else if (TempType == typeof (float))\r
406                                 Result = (float)value1 + (float)value2;\r
407                         else if (TempType == typeof (double))\r
408                                 Result = (double)value1 + (double)value2;\r
409                         else if (TempType == typeof (decimal))\r
410                                 Result = (decimal)value1 + (decimal)value2;\r
411                         // FIXME:\r
412                         //else if (TempType == typeof (DateTime))\r
413                         //      Result = (DateTime)value1 + (DateTime)value2;\r
414                         \r
415                         return Result;\r
416                 }\r
417 \r
418 \r
419                 // This method is shouldnt never invoked\r
420                 public override bool Test (DataRow Row)\r
421                 {\r
422                         throw new EvaluateException ();\r
423                 }\r
424         }\r
425 \r
426         /// <summary>\r
427         ///  Class for -\r
428         /// </summary>\r
429         internal class ExpressionSubtraction : ExpressionElement\r
430         {\r
431                 public ExpressionSubtraction (string exp1, string exp2)\r
432                 {                       \r
433                         this.exp1 = exp1;\r
434                         this.exp2 = exp2;\r
435                         ParseExpression (exp1);\r
436                         ParseExpression (exp2);\r
437                 }\r
438                 \r
439                 public override object Result (DataRow Row) \r
440                 {                       \r
441                         return CalculateResult (Row);\r
442                 }\r
443                 \r
444                 // This method is shouldnt never invoked\r
445                 public override bool Test (DataRow Row)\r
446                 {\r
447                         throw new EvaluateException ();\r
448                 }\r
449 \r
450                 protected override object Calculate (object value1, object value2, Type TempType) \r
451                 {\r
452                         object Result = null;                   \r
453 \r
454                         // FIXME:\r
455                         //if (TempType == typeof (string))\r
456                         //      Result = (string)value1 - (string)value2;\r
457                         if (TempType == typeof (long))\r
458                                 Result = (long)value1 - (long)value2;\r
459                         else if (TempType == typeof (int))\r
460                                 Result = (int)value1 - (int)value2;\r
461                         else if (TempType == typeof (short))\r
462                                 Result = (short)value1 - (short)value2;\r
463                         else if (TempType == typeof (ulong))\r
464                                 Result = (ulong)value1 + (ulong)value2;\r
465                         else if (TempType == typeof (uint))\r
466                                 Result = (uint)value1 - (uint)value2;\r
467                         else if (TempType == typeof (ushort))\r
468                                 Result = (ushort)value1 - (ushort)value2;\r
469                         else if (TempType == typeof (byte))\r
470                                 Result = (byte)value1 - (byte)value2;\r
471                         else if (TempType == typeof (sbyte))\r
472                                 Result = (sbyte)value1 - (sbyte)value2;\r
473                                 // FIXME:\r
474                                 //else if (TempType == typeof (bool))\r
475                                 //      Result = (bool)value1 - (bool)value2;\r
476                         else if (TempType == typeof (float))\r
477                                 Result = (float)value1 - (float)value2;\r
478                         else if (TempType == typeof (double))\r
479                                 Result = (double)value1 - (double)value2;\r
480                         else if (TempType == typeof (decimal))\r
481                                 Result = (decimal)value1 - (decimal)value2;\r
482                         // FIXME:\r
483                         //else if (TempType == typeof (DateTime))\r
484                         //      Result = (DateTime)value1 - (DateTime)value2;\r
485                         \r
486                         return Result;\r
487                 }\r
488         }\r
489 \r
490         /// <summary>\r
491         ///  Class for *\r
492         /// </summary>\r
493         internal class ExpressionMultiply : ExpressionElement\r
494         {\r
495                 public ExpressionMultiply (string exp1, string exp2)\r
496                 {                       \r
497                         this.exp1 = exp1;\r
498                         this.exp2 = exp2;\r
499                         ParseExpression (exp1);\r
500                         ParseExpression (exp2);\r
501                 }\r
502                 \r
503                 public override Type ResultType (DataRow Row)\r
504                 {\r
505                         Type ResultType = null;\r
506                         ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
507                         ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
508                         Type t1 = E1.ResultType (Row);\r
509                         Type t2 = E2.ResultType (Row);\r
510                                 \r
511                         if (t1 == typeof (string) || t2 == typeof (string))\r
512                                 throw new EvaluateException ("Cannon perform '*' operation on " + t1.ToString () + \r
513                                         " and " + t2.ToString ());\r
514 \r
515                         else if (t1 == typeof (long) || t2 == typeof (long))\r
516                                 ResultType = typeof (long);\r
517 \r
518                         else if (t1 == typeof (int) || t2 == typeof (int))\r
519                                 ResultType = typeof (int);\r
520 \r
521                         return ResultType;\r
522                 }\r
523 \r
524                 public override object Result (DataRow Row) \r
525                 {\r
526                         return CalculateResult (Row);\r
527                 }\r
528                 \r
529                 public override bool Test (DataRow Row)\r
530                 {\r
531                         throw new EvaluateException ();\r
532                 }\r
533 \r
534                 protected override object Calculate (object value1, object value2, Type TempType) \r
535                 {\r
536                         object Result = null;                   \r
537 \r
538                         if (TempType == typeof (long))\r
539                                 Result = (long)value1 * (long)value2;\r
540                         else if (TempType == typeof (int))\r
541                                 Result = (int)value1 * (int)value2;\r
542                         else if (TempType == typeof (short))\r
543                                 Result = (short)value1 * (short)value2;\r
544                         else if (TempType == typeof (ulong))\r
545                                 Result = (ulong)value1 * (ulong)value2;\r
546                         else if (TempType == typeof (uint))\r
547                                 Result = (uint)value1 * (uint)value2;\r
548                         else if (TempType == typeof (ushort))\r
549                                 Result = (ushort)value1 * (ushort)value2;\r
550                         else if (TempType == typeof (byte))\r
551                                 Result = (byte)value1 * (byte)value2;\r
552                         else if (TempType == typeof (sbyte))\r
553                                 Result = (sbyte)value1 * (sbyte)value2;\r
554                                 // FIXME:\r
555                                 //else if (TempType == typeof (bool))\r
556                                 //      Result = (bool)value1 * (bool)value2;\r
557                         else if (TempType == typeof (float))\r
558                                 Result = (float)value1 * (float)value2;\r
559                         else if (TempType == typeof (double))\r
560                                 Result = (double)value1 * (double)value2;\r
561                         else if (TempType == typeof (decimal))\r
562                                 Result = (decimal)value1 * (decimal)value2;\r
563                         // FIXME:\r
564                         //else if (TempType == typeof (DateTime))\r
565                         //      Result = (DateTime)value1 * (DateTime)value2;\r
566                         \r
567                         return Result;\r
568                 }\r
569 \r
570         }\r
571 \r
572         /// <summary>\r
573         ///  Class for *\r
574         /// </summary>\r
575         internal class ExpressionDivide : ExpressionElement\r
576         {\r
577                 public ExpressionDivide (string exp1, string exp2)\r
578                 {                       \r
579                         this.exp1 = exp1;\r
580                         this.exp2 = exp2;\r
581                         ParseExpression (exp1);\r
582                         ParseExpression (exp2);\r
583                 }\r
584                 \r
585                 public override object Result (DataRow Row) \r
586                 {\r
587                         return CalculateResult (Row);\r
588                 }\r
589                 \r
590                 // This method is shouldnt never invoked\r
591                 public override bool Test (DataRow Row)\r
592                 {\r
593                         throw new EvaluateException ();\r
594                 }\r
595 \r
596                 protected  override object Calculate (object value1, object value2, Type TempType) \r
597                 {\r
598                         object Result = null;                   \r
599 \r
600                         if (TempType == typeof (long))\r
601                                 Result = (long)value1 / (long)value2;\r
602                                 // FIXME: \r
603                                 //else if (TempType == typeof (int))\r
604                                 //      Result = (string)value1 / (string)value2;\r
605                         else if (TempType == typeof (int))\r
606                                 Result = (int)value1 / (int)value2;\r
607                         else if (TempType == typeof (short))\r
608                                 Result = (short)value1 / (short)value2;\r
609                         else if (TempType == typeof (ulong))\r
610                                 Result = (ulong)value1 / (ulong)value2;\r
611                         else if (TempType == typeof (uint))\r
612                                 Result = (uint)value1 / (uint)value2;\r
613                         else if (TempType == typeof (ushort))\r
614                                 Result = (ushort)value1 / (ushort)value2;\r
615                         else if (TempType == typeof (byte))\r
616                                 Result = (byte)value1 / (byte)value2;\r
617                         else if (TempType == typeof (sbyte))\r
618                                 Result = (sbyte)value1 / (sbyte)value2;\r
619                                 // FIXME:\r
620                                 //else if (TempType == typeof (bool))\r
621                                 //      Result = (bool)value1 // (bool)value2;\r
622                         else if (TempType == typeof (float))\r
623                                 Result = (float)value1 / (float)value2;\r
624                         else if (TempType == typeof (double))\r
625                                 Result = (double)value1 / (double)value2;\r
626                         else if (TempType == typeof (decimal))\r
627                                 Result = (decimal)value1 / (decimal)value2;\r
628                         // FIXME:\r
629                         //else if (TempType == typeof (DateTime))\r
630                         //      Result = (DateTime)value1 / (DateTime)value2;\r
631                         \r
632                         return Result;\r
633                 }\r
634         }\r
635 \r
636         /// <summary>\r
637         ///  Class for *\r
638         /// </summary>\r
639         internal class ExpressionModulus : ExpressionElement\r
640         {\r
641                 public ExpressionModulus (string exp1, string exp2)\r
642                 {                       \r
643                         this.exp1 = exp1;\r
644                         this.exp2 = exp2;\r
645                         ParseExpression (exp1);\r
646                         ParseExpression (exp2);\r
647                 }\r
648                 \r
649                 public override object Result (DataRow Row) \r
650                 {\r
651                         return CalculateResult (Row);\r
652                 }\r
653                 \r
654                 // This method is shouldnt never invoked\r
655                 public override bool Test (DataRow Row)\r
656                 {\r
657                         throw new EvaluateException ();\r
658                 }\r
659 \r
660                 protected  override object Calculate (object value1, object value2, Type TempType) \r
661                 {\r
662                         object Result = null;                   \r
663 \r
664                         if (TempType == typeof (long))\r
665                                 Result = (long)value1 % (long)value2;\r
666                                 // FIXME: \r
667                                 //else if (TempType == typeof (int))\r
668                                 //      Result = (string)value1 % (string)value2;\r
669                         else if (TempType == typeof (int))\r
670                                 Result = (int)value1 % (int)value2;\r
671                         else if (TempType == typeof (short))\r
672                                 Result = (short)value1 % (short)value2;\r
673                         else if (TempType == typeof (ulong))\r
674                                 Result = (ulong)value1 % (ulong)value2;\r
675                         else if (TempType == typeof (uint))\r
676                                 Result = (uint)value1 % (uint)value2;\r
677                         else if (TempType == typeof (ushort))\r
678                                 Result = (ushort)value1 % (ushort)value2;\r
679                         else if (TempType == typeof (byte))\r
680                                 Result = (byte)value1 % (byte)value2;\r
681                         else if (TempType == typeof (sbyte))\r
682                                 Result = (sbyte)value1 % (sbyte)value2;\r
683                                 // FIXME:\r
684                                 //else if (TempType == typeof (bool))\r
685                                 //      Result = (bool)value1 // (bool)value2;\r
686                         else if (TempType == typeof (float))\r
687                                 Result = (float)value1 % (float)value2;\r
688                         else if (TempType == typeof (double))\r
689                                 Result = (double)value1 % (double)value2;\r
690                         else if (TempType == typeof (decimal))\r
691                                 Result = (decimal)value1 % (decimal)value2;\r
692                         // FIXME:\r
693                         //else if (TempType == typeof (DateTime))\r
694                         //      Result = (DateTime)value1 / (DateTime)value2;\r
695                         \r
696                         return Result;\r
697                 }\r
698         }\r
699 \r
700         //\r
701         // _____A_G_G_R_E_G_A_T_E_S_____\r
702         //\r
703 \r
704         internal class ExpressionAggregate : ExpressionElement\r
705         {\r
706                 \r
707                 public ExpressionAggregate()\r
708                 {\r
709                 }\r
710 \r
711                 public ExpressionAggregate(string s)\r
712                 {\r
713                         s = ExpressionElement.ValidateExpression (s);\r
714                         ParseExpression (s);\r
715                 }\r
716 \r
717                 \r
718                 public override bool Test (DataRow Row)\r
719                 {\r
720                         throw new EvaluateException ();\r
721                 }\r
722 \r
723                 public override object Result(DataRow Row)\r
724                 {\r
725                         DataRow[] rows = new DataRow[Row.Table.Rows.Count];\r
726                         Row.Table.Rows.CopyTo(rows, 0);\r
727                         return ((ExpressionAggregate)Elements[0]).Result(rows);\r
728                 }\r
729 \r
730                 public virtual object Result(DataRow[] rows)\r
731                 {\r
732                         return ((ExpressionAggregate)Elements[0]).Result(rows);\r
733                 }\r
734 \r
735 \r
736                 protected virtual void ParseParameters (string s)\r
737                 {\r
738                         string stemp = s.ToLower ();\r
739                         bool inString = false;\r
740                         string p1 = null;\r
741 \r
742                         // find (\r
743                         while (!s.StartsWith ("("))\r
744                                 s = s.Remove (0, 1);\r
745                         \r
746                         // remove (\r
747                         s = s.Remove (0, 1);\r
748 \r
749                         int parentheses = 0;\r
750                         for (int i = 0; i < s.Length; i++) \r
751                         {\r
752 \r
753                                 if (s [i] == '\'')\r
754                                         inString = !inString;\r
755                                 else if (s [i] == '(')\r
756                                         parentheses++;\r
757                                 else if (s [i] == ')')\r
758                                         parentheses--;\r
759 \r
760                                 if ((s [i] == ',' ||  s [i] == ')') && !inString && parentheses == -1) \r
761                                 { // Parameter changed\r
762 \r
763                                         if (p1 == null) \r
764                                         {\r
765                                                 p1 = s.Substring (0, i);\r
766                                                 break;\r
767                                         }\r
768                                 }\r
769                         }\r
770 \r
771                         if (p1 == null)\r
772                                 throw new Exception ();\r
773 \r
774                         ParseExpression (p1);           \r
775                 }\r
776                 \r
777         }\r
778 \r
779         /// <summary>\r
780         ///  Class for Sum (column_Name)\r
781         /// </summary\r
782         internal class ExpressionSum : ExpressionAggregate\r
783         {\r
784                 public ExpressionSum (string exp1)\r
785                 {\r
786                         ParseParameters (exp1);\r
787                 }\r
788 \r
789                 public override object Result(DataRow[] rows)\r
790                 {\r
791                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
792                         object value1 = E1.Result (rows[0]);\r
793                         Type t1 = value1.GetType ();\r
794                         object result = 0;\r
795                         \r
796                         // This could be optimized. If E1 is single element (Not child or parent) the\r
797                         // result of Sum() aggregate is allways same\r
798 \r
799                         if (E1 is ExpressionSingleElement) \r
800                         {\r
801                                 \r
802                                 // This should be optimized somehow\r
803                                 for (int i = 0; i < rows.Length; i++) \r
804                                 {\r
805 \r
806                                         // TODO: other types and exceptions\r
807                                         object v = E1.Result (rows[i]);\r
808                                         t1 = v.GetType ();\r
809 \r
810                                         if (v == null || v == DBNull.Value)\r
811                                                 continue;\r
812 \r
813                                         if (t1 == typeof (long)) \r
814                                         {\r
815                                                 result = (long)result + (long)v;\r
816                                         }\r
817                                         else if (t1 == typeof (int)) \r
818                                         {\r
819                                                 result = (int)result + (int)v;\r
820                                         }\r
821                                         else if (t1 == typeof (short)) \r
822                                         {\r
823                                                 result = (short)result + (short)v;\r
824                                         }\r
825                                         else if (t1 == typeof (double)) \r
826                                         {\r
827                                                 result = (double)result + (double)v;\r
828                                         }\r
829                                         else if (t1 == typeof (float)) \r
830                                         {\r
831                                                 result = (float)result + (float)v;\r
832                                         }\r
833                                         else\r
834                                                 throw new NotImplementedException ();\r
835                                 }\r
836                         }\r
837                         \r
838                         return result;\r
839                 }\r
840 \r
841                 \r
842                 //\r
843                 // Copy: This method is copy-paste in every Aggregate class.\r
844                 //\r
845         }\r
846 \r
847         /// <summary>\r
848         ///  Class for Avg (column_Name)\r
849         /// </summary\r
850         internal class ExpressionAvg : ExpressionAggregate\r
851         {\r
852                 public ExpressionAvg (string exp1)\r
853                 {\r
854                         ParseParameters (exp1);\r
855                 }\r
856 \r
857                 public override object Result(DataRow[] rows)\r
858                 {\r
859                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
860                         object value1 = E1.Result (rows[0]);\r
861                         Type original = value1.GetType ();\r
862                         object result = null;\r
863                         \r
864                         if (E1 is ExpressionSingleElement) \r
865                         {\r
866                                 \r
867                                 Type t1 = null;\r
868                                 // This should be optimized somehow\r
869                                 for (int i = 0; i < rows.Length; i++) \r
870                                 {\r
871                                        \r
872                                         // TODO: other types and exceptions\r
873                                         object v = E1.Result (rows[i]);\r
874 \r
875                                         if (v == null || v == DBNull.Value)\r
876                                                 continue;\r
877 \r
878                                         t1 = v.GetType ();\r
879 \r
880                                         if (result == null)\r
881                                                 result = 0;\r
882                                         \r
883                                         if (t1 == typeof (long)) \r
884                                         {\r
885                                                 result = (long)result + (long)v;\r
886                                         }\r
887                                         else if (t1 == typeof (int)) \r
888                                         {\r
889                                                 result = (int)result + (int)v;\r
890                                         }\r
891                                         else if (t1 == typeof (short)) \r
892                                         {\r
893                                                 result = (short)result + (short)v;\r
894                                         }\r
895                                         else if (t1 == typeof (double)) \r
896                                         {\r
897                                                 result = (double)result + (double)v;\r
898                                         }\r
899                                         else if (t1 == typeof (float)) \r
900                                         {\r
901                                                 result = (float)result + (float)v;\r
902                                         }\r
903                                         else\r
904                                                 throw new NotImplementedException ();\r
905                                 }\r
906 \r
907                                 // TODO: types\r
908 \r
909                                 if (t1 == typeof (long))\r
910                                         result = (long)result / rows.Length;\r
911                                 else if (t1 == typeof (int))\r
912                                         result = (int)result / rows.Length;\r
913                                 else if (t1 == typeof (short))\r
914                                         result = (short)result / rows.Length;\r
915                                 else if (t1 == typeof (double))\r
916                                         result = (double)result / rows.Length;\r
917                         }\r
918                         \r
919                         return result;\r
920                 }\r
921 \r
922                 /// <summary>\r
923                 ///  This is used from ExpressionStdDev for evaluating avg.\r
924                 /// </summary>\r
925                 public ExpressionAvg (ExpressionElement E)\r
926                 {\r
927                         Elements.Add (E);\r
928                 }\r
929         \r
930         }\r
931 \r
932         /// <summary>\r
933         ///  Class for Min (column_Name)\r
934         /// </summary\r
935         internal class ExpressionMin : ExpressionAggregate\r
936         {\r
937                 public ExpressionMin (string exp1)\r
938                 {\r
939                         ParseParameters (exp1);\r
940                 }\r
941 \r
942                 public override object Result(DataRow[] rows)\r
943                 {\r
944                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
945                         object value1 = E1.Result (rows[0]);\r
946                         Type original = value1.GetType ();\r
947                         object result = null;\r
948                         \r
949                         if (E1 is ExpressionSingleElement) \r
950                         {\r
951                                 \r
952                                 Type t1 = null;\r
953                                 // This should be optimized somehow\r
954                                 for (int i = 0; i < rows.Length; i++)\r
955                                 {\r
956                                        \r
957                                         // TODO: other types and exceptions\r
958                                         object v = E1.Result (rows[i]);\r
959 \r
960                                         if (v == null || v == DBNull.Value)\r
961                                                 continue;\r
962 \r
963                                         t1 = v.GetType ();\r
964 \r
965                                         if (result == null)\r
966                                                 result = 0;\r
967 \r
968                                         object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
969                                                 BindingFlags.InvokeMethod, null, \r
970                                                 v, \r
971                                                 new object [] {result});\r
972 \r
973                                         if ((int)CompResult < 0)\r
974                                                 result = v;\r
975 \r
976                                 }\r
977                         }\r
978                         \r
979                         return result;\r
980                 }\r
981 \r
982                 \r
983         }\r
984 \r
985         /// <summary>\r
986         ///  Class for Max (column_Name)\r
987         /// </summary\r
988         internal class ExpressionMax : ExpressionAggregate\r
989         {\r
990                 public ExpressionMax (string exp1)\r
991                 {\r
992                         ParseParameters (exp1);\r
993                 }\r
994 \r
995                 public override object Result(DataRow[] rows)\r
996                 {\r
997                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
998                         object value1 = E1.Result (rows[0]);\r
999                         Type original = value1.GetType ();\r
1000                         object result = null;\r
1001                         \r
1002                         if (E1 is ExpressionSingleElement) \r
1003                         {\r
1004                                 \r
1005                                 Type t1 = null;\r
1006                                 // This should be optimized somehow\r
1007                                 for (int i = 0; i < rows.Length; i++) \r
1008                                 {\r
1009                                        \r
1010                                         // TODO: other types and exceptions\r
1011                                         object v = E1.Result (rows[i]);\r
1012 \r
1013                                         if (v == null || v == DBNull.Value)\r
1014                                                 continue;\r
1015 \r
1016                                         t1 = v.GetType ();\r
1017 \r
1018                                         if (result == null)\r
1019                                                 result = 0;\r
1020 \r
1021                                         object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
1022                                                 BindingFlags.InvokeMethod, null, \r
1023                                                 v, \r
1024                                                 new object [] {result});\r
1025 \r
1026                                         if ((int)CompResult > 0)\r
1027                                                 result = v;\r
1028 \r
1029                                 }\r
1030                         }\r
1031                         \r
1032                         return result;\r
1033                 }\r
1034 \r
1035                 \r
1036         }\r
1037 \r
1038 \r
1039         /// <summary>\r
1040         ///  Class for count (column)\r
1041         /// </summary>\r
1042         internal class ExpressionCount : ExpressionAggregate\r
1043         {\r
1044                 public ExpressionCount (string exp1)\r
1045                 {\r
1046                         ParseParameters (exp1);\r
1047                 }\r
1048                 \r
1049                 public override object Result(DataRow[] rows)\r
1050                 {\r
1051                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
1052                         int count = 0;\r
1053 \r
1054                         if (E1 is ExpressionSingleElement) \r
1055                                 count = rows.Length;\r
1056                         \r
1057                         return count;\r
1058                 }\r
1059 \r
1060                 public override object Result (DataRow Row) \r
1061                 {\r
1062                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
1063                         int count = 0;\r
1064 \r
1065                         if (E1 is ExpressionSingleElement) \r
1066                         {\r
1067                                 \r
1068                                 count = Row.Table.Rows.Count;\r
1069                         }\r
1070                         \r
1071                         return count;\r
1072                 }\r
1073         }\r
1074 \r
1075 \r
1076         /// <summary>\r
1077         ///  Class for StdDev (column)\r
1078         /// </summary>\r
1079         internal class ExpressionStdev : ExpressionAggregate\r
1080         {\r
1081                 public ExpressionStdev (string exp1)\r
1082                 {               \r
1083                         ParseParameters (exp1);\r
1084                 }\r
1085 \r
1086                 public override object Result(DataRow[] rows)\r
1087                 {\r
1088                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
1089                         ExpressionAvg Avg = new ExpressionAvg (E1);\r
1090 \r
1091                         object tempAvg = Avg.Result (rows[0]);\r
1092                         double avg = 0;\r
1093                         double sum = 0;\r
1094                         double result = 0;\r
1095 \r
1096                         if (tempAvg.GetType () == typeof (int))\r
1097                                 avg = (double)(int)tempAvg;\r
1098                         \r
1099                         if (E1 is ExpressionSingleElement) \r
1100                         {\r
1101 \r
1102                                 for (int i = 0; i <rows.Length; i++)\r
1103                                 {\r
1104                                         // (value - avg)²\r
1105                                         object v = E1.Result (rows[i]);\r
1106 \r
1107                                         if (v == null || v == DBNull.Value)\r
1108                                                 continue;\r
1109 \r
1110                                         if (v.GetType () == typeof (long))\r
1111                                                 sum = avg - (long)v;\r
1112                                         else if (v.GetType () == typeof (int))\r
1113                                                 sum = avg - (int)v;\r
1114                                         else if (v.GetType () == typeof (short))\r
1115                                                 sum = avg - (short)v;\r
1116                                         else\r
1117                                                 throw new NotImplementedException ();\r
1118 \r
1119                                         result += Math.Pow (sum, 2);\r
1120                                 }\r
1121                                 \r
1122                                 result = result / (rows.Length - 1);\r
1123                                 result = Math.Sqrt (result);\r
1124                         }\r
1125 \r
1126                         return result;\r
1127                 }\r
1128                 \r
1129                 \r
1130         }\r
1131 \r
1132         /// <summary>\r
1133         ///  Class for Var (column)\r
1134         /// </summary>\r
1135         internal class ExpressionVar : ExpressionAggregate\r
1136         {\r
1137                 public ExpressionVar (string exp1)\r
1138                 {\r
1139                         ParseParameters (exp1);\r
1140                 }\r
1141 \r
1142                 public override object Result(DataRow[] rows)\r
1143                 {\r
1144                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
1145                         ExpressionAvg Avg = new ExpressionAvg (E1);\r
1146 \r
1147                         object tempAvg = Avg.Result (rows[0]);\r
1148                         double avg = 0;\r
1149                         double sum = 0;\r
1150                         double result = 0;\r
1151 \r
1152                         if (tempAvg.GetType () == typeof (int))\r
1153                                 avg = (double)(int)tempAvg;\r
1154                         \r
1155                         if (E1 is ExpressionSingleElement) \r
1156                         {\r
1157 \r
1158                                 for (int i = 0; i < rows.Length; i++)\r
1159                                 {\r
1160 \r
1161                                        \r
1162                                         // (value - avg)²\r
1163                                         object v = E1.Result (rows[i]);\r
1164 \r
1165                                         if (v == null || v == DBNull.Value)\r
1166                                                 continue;\r
1167 \r
1168                                         if (v.GetType () == typeof (long))\r
1169                                                 sum = avg - (long)v;\r
1170                                         else if (v.GetType () == typeof (int))\r
1171                                                 sum = avg - (int)v;\r
1172                                         else if (v.GetType () == typeof (short))\r
1173                                                 sum = avg - (short)v;\r
1174                                         else\r
1175                                                 throw new NotImplementedException ();\r
1176 \r
1177                                         result += Math.Pow (sum, 2);\r
1178                                 }\r
1179                                 \r
1180                                 result = result / (rows.Length - 1);\r
1181                         }\r
1182 \r
1183                         return result;\r
1184                 }\r
1185                 \r
1186                 \r
1187         }\r
1188 \r
1189         // \r
1190         // _____F_U_ N_C_T_I_O_N_S_______\r
1191         //\r
1192 \r
1193         /// <summary>\r
1194         ///  Class for len (string) function\r
1195         /// </summary>\r
1196         internal class ExpressionLen : ExpressionElement\r
1197         {\r
1198                 public ExpressionLen (string exp1)\r
1199                 {                       \r
1200                         _ResultType = typeof (int);\r
1201                         ParseParameters (exp1);\r
1202                 }\r
1203                 \r
1204                 public override object Result (DataRow Row) \r
1205                 {\r
1206                         ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
1207                         object value1 = E1.Result (Row);\r
1208                         \r
1209                         return value1.ToString ().Length;\r
1210                 }\r
1211                 \r
1212                 public override bool Test (DataRow Row)\r
1213                 {\r
1214                         throw new EvaluateException ();\r
1215                 }\r
1216 \r
1217                 public void ParseParameters (string s)\r
1218                 {\r
1219                         string stemp = s.ToLower ();\r
1220                         bool inString = false;\r
1221                         string p1 = null;\r
1222 \r
1223                         // find (\r
1224                         while (!s.StartsWith ("("))\r
1225                                 s = s.Remove (0, 1);\r
1226 \r
1227                         // remove (\r
1228                         s = s.Remove (0, 1);\r
1229                         int parentheses = 0;\r
1230                         for (int i = 0; i < s.Length; i++) \r
1231                         {\r
1232 \r
1233                                 if (s [i] == '\'')\r
1234                                         inString = !inString;\r
1235                                 else if (s [i] == '(')\r
1236                                         parentheses++;\r
1237                                 else if (s [i] == ')')\r
1238                                         parentheses--;\r
1239 \r
1240                                 if ((s [i] == ',' ||  s [i] == ')') && !inString && parentheses == -1) \r
1241                                 { // Parameter changed\r
1242 \r
1243                                         if (p1 == null) \r
1244                                         {\r
1245                                                 p1 = s.Substring (0, i);\r
1246                                                 break;\r
1247                                         }\r
1248                                 }\r
1249                         }\r
1250 \r
1251                         if (p1 == null)\r
1252                                 throw new Exception ();\r
1253 \r
1254                         ParseExpression (p1);           \r
1255                 }\r
1256         }\r
1257 \r
1258         /// <summary>\r
1259         ///  Class for iif (exp1, truepart, falsepart) function\r
1260         /// </summary>\r
1261         internal class ExpressionIif : ExpressionElement\r
1262         {\r
1263                 public ExpressionIif (string exp)\r
1264                 {       \r
1265                         ParseParameters (exp);\r
1266                 }\r
1267 \r
1268                 public override object Result (DataRow Row) \r
1269                 {\r
1270                         ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
1271                         ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
1272                         ExpressionElement E3 = ((ExpressionElement)Elements [2]);\r
1273 \r
1274                         if (E1.Test (Row)) // expression\r
1275                                 return E2.Result (Row); // truepart\r
1276                         else\r
1277                                 return E3.Result (Row); // false part                   \r
1278                 }\r
1279                 \r
1280                 // This method is shouldnt never invoked\r
1281                 public override bool Test (DataRow Row)\r
1282                 {\r
1283                         throw new EvaluateException ();\r
1284                 }\r
1285 \r
1286                 public override Type ResultType (DataRow Row)\r
1287                 {                                               \r
1288                         ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
1289                         ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
1290                         ExpressionElement E3 = ((ExpressionElement)Elements [2]);\r
1291                         \r
1292                         if (E1.Test (Row)) // expression\r
1293                                 return E2.Result (Row).GetType (); // truepart\r
1294                         else\r
1295                                 return E3.Result (Row).GetType (); // false part                        \r
1296                 }\r
1297 \r
1298                 /// <summary>\r
1299                 ///  Parses expressions in parameters (exp, truepart, falsepart)\r
1300                 /// </summary>\r
1301                 private void ParseParameters (string s)\r
1302                 {\r
1303                         bool inString = false;\r
1304                         string stemp = s.ToLower ();\r
1305                         string p1 = null;\r
1306                         string p2 = null;\r
1307                         string p3 = null;\r
1308                         s = s.Substring (stemp.IndexOf ("iif") + 3);\r
1309 \r
1310                         // find (\r
1311                         while (!s.StartsWith ("("))\r
1312                                 s = s.Remove (0, 1);\r
1313 \r
1314                         // remove (\r
1315                         s = s.Remove (0, 1);\r
1316                         int parentheses = 0;\r
1317                         for (int i = 0; i < s.Length; i++) \r
1318                         {\r
1319 \r
1320                                 if (s [i] == '\'')\r
1321                                         inString = !inString;\r
1322                                 else if (s [i] == '(')\r
1323                                         parentheses++;\r
1324                                 else if (s [i] == ')')\r
1325                                         parentheses--;\r
1326 \r
1327                                 if ((s [i] == ',' && !inString && parentheses == 0) || \r
1328                                         (s [i] == ')' && i == (s.Length -1))) \r
1329                                 { // Parameter changed\r
1330 \r
1331                                         if (p1 == null) \r
1332                                         {\r
1333                                                 p1 = s.Substring (0, i);\r
1334                                                 s = s.Substring (i + 1);\r
1335                                                 i = 0;\r
1336                                         }\r
1337 \r
1338                                         else if (p2 == null) \r
1339                                         {\r
1340                                                 p2 = s.Substring (0, i);\r
1341                                                 s = s.Substring (i + 1);\r
1342                                                 i = 0;\r
1343                                         }\r
1344 \r
1345                                         else if (p3 == null) \r
1346                                         {\r
1347                                                 p3 = s.Substring (0, i);\r
1348                                                 s = s.Substring (i + 1);\r
1349                                                 i = 0;\r
1350                                         }\r
1351 \r
1352                                         else\r
1353                                                 throw new Exception (); // FIXME: What exception\r
1354                                 }\r
1355                         }\r
1356 \r
1357                         if (p1 == null || p2 == null || p3 == null)\r
1358                                 throw new Exception ();\r
1359 \r
1360                         ParseExpression (p1);\r
1361                         ParseExpression (p2);\r
1362                         ParseExpression (p3);\r
1363                 }\r
1364         }\r
1365 \r
1366         /// <summary>\r
1367         ///  Class for isnull (expression, returnvalue) function\r
1368         /// </summary>\r
1369         internal class ExpressionIsNull : ExpressionElement\r
1370         {\r
1371                 public ExpressionIsNull (string exp)\r
1372                 {                       \r
1373                         ParseParameters (exp);\r
1374                 }\r
1375                 \r
1376                 public override object Result (DataRow Row) \r
1377                 {\r
1378                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
1379                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
1380                         \r
1381                         object R1 = E1.Result (Row);\r
1382                         object value1 = null;\r
1383                         if (R1 == null || R1 == DBNull.Value)\r
1384                                 return E2.Result (Row);\r
1385                         else\r
1386                                 return R1;\r
1387                 }\r
1388 \r
1389                 public override Type ResultType (DataRow Row)\r
1390                 {\r
1391                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
1392                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
1393                         \r
1394                         object R1 = E1.Result (Row);\r
1395                         object value1 = null;\r
1396                         if (R1 == null || R1 == DBNull.Value)\r
1397                                 return E2.Result (Row).GetType ();\r
1398                         else\r
1399                                 return R1.GetType ();\r
1400                 }\r
1401                 \r
1402                 /// <summary>\r
1403                 ///  IsNull function does not return boolean value, so throw exception\r
1404                 /// </summary>\r
1405                 public override bool Test (DataRow Row)\r
1406                 {\r
1407                         throw new EvaluateException ();\r
1408                 }\r
1409 \r
1410                 /// <summary>\r
1411                 ///  Parses parameters of function and invoke ParseExpression methods\r
1412                 /// </summary>\r
1413                 private void ParseParameters (string s)\r
1414                 {\r
1415                         bool inString = false;\r
1416                         string stemp = s.ToLower ();\r
1417                         string p1 = null;\r
1418                         string p2 = null;\r
1419 \r
1420                         s = s.Substring (stemp.IndexOf ("isnull") + 6);\r
1421 \r
1422                         // find (\r
1423                         while (!s.StartsWith ("("))\r
1424                                 s = s.Remove (0, 1);\r
1425 \r
1426                         // remove (\r
1427                         s = s.Remove (0, 1);\r
1428                         int parentheses = 0;\r
1429                         for (int i = 0; i < s.Length; i++) \r
1430                         {\r
1431 \r
1432                                 if (s [i] == '\'')\r
1433                                         inString = !inString;\r
1434                                 else if (s [i] == '(')\r
1435                                         parentheses++;\r
1436                                 else if (s [i] == ')')\r
1437                                         parentheses--;\r
1438 \r
1439                                 if ((s [i] == ',' && !inString && parentheses == 0) || \r
1440                                         (s [i] == ')' && i == (s.Length -1))) \r
1441                                 { // Parameter changed\r
1442 \r
1443                                         if (p1 == null) \r
1444                                         {\r
1445                                                 p1 = s.Substring (0, i);\r
1446                                                 s = s.Substring (i + 1);\r
1447                                                 i = 0;\r
1448                                         }\r
1449 \r
1450                                         else if (p2 == null) \r
1451                                         {\r
1452                                                 p2 = s.Substring (0, i);\r
1453                                                 s = s.Substring (i + 1);\r
1454                                                 i = 0;\r
1455                                         }\r
1456 \r
1457                                         else\r
1458                                                 throw new Exception (); // FIXME: What exception\r
1459                                 }\r
1460                         }\r
1461 \r
1462                         if (p1 == null || p2 == null)\r
1463                                 throw new Exception ();\r
1464 \r
1465                         ParseExpression (p1);\r
1466                         ParseExpression (p2);\r
1467                 }\r
1468         }\r
1469 \r
1470         /// <summary>\r
1471         ///  Class for Substring (expression, start, length) function\r
1472         /// </summary>\r
1473         internal class ExpressionSubstring : ExpressionElement\r
1474         {\r
1475                 public ExpressionSubstring (string exp)\r
1476                 {                       \r
1477                         ParseParameters (exp);\r
1478                         _ResultType = typeof (string);\r
1479                 }\r
1480                 \r
1481                 public override object Result (DataRow Row) \r
1482                 {\r
1483                         ExpressionElement E1 = (ExpressionElement)Elements [0];\r
1484                         ExpressionElement E2 = (ExpressionElement)Elements [1];\r
1485                         ExpressionElement E3 = (ExpressionElement)Elements [2];\r
1486                         \r
1487                         object value1 = E1.Result (Row);\r
1488                         object value2 = E2.Result (Row);\r
1489                         object value3 = E3.Result (Row);\r
1490                         Type t1 = value1.GetType ();\r
1491                         Type t2 = value2.GetType ();\r
1492                         Type t3 = value3.GetType ();\r
1493 \r
1494                         if (value1 == null || value2 == null || value3 == null \r
1495                                 || value1 == DBNull.Value || value2 == DBNull.Value || value3 == DBNull.Value)\r
1496                                 return string.Empty;\r
1497 \r
1498                         if (t1 != typeof (string))\r
1499                                 throw new Exception (); // FIXME: what exception\r
1500                         else if (t2 != typeof (int))\r
1501                                 throw new EvaluateException ("Type mismatch is function argument: Substring (), argument 2, excepted System.Int32");\r
1502                         else if (t3 != typeof (int))\r
1503                                 throw new EvaluateException ("Type mismatch is function argument: Substring (), argument 3, excepted System.Int32");\r
1504 \r
1505                         string str = value1.ToString ();\r
1506                         int start = (int)value2;\r
1507                         int length = (int)value3;\r
1508 \r
1509                         if (str.Length < start)\r
1510                                 str =  string.Empty;\r
1511                         else \r
1512                         {\r
1513                                 if ((start + length - 1) > str.Length)\r
1514                                         str = str.Substring (start - 1);\r
1515                                 else\r
1516                                         str = str.Substring (start - 1, length);\r
1517                         }\r
1518 \r
1519                         return str;\r
1520                 }\r
1521 \r
1522                 /// <summary>\r
1523                 ///  IsNull function does not return boolean value, so throw exception\r
1524                 /// </summary>\r
1525                 public override bool Test (DataRow Row)\r
1526                 {\r
1527                         throw new EvaluateException ();\r
1528                 }\r
1529 \r
1530                 /// <summary>\r
1531                 ///  Parses parameters of function and invoke ParseExpression methods\r
1532                 /// </summary>\r
1533                 private void ParseParameters (string s)\r
1534                 {\r
1535                         bool inString = false;\r
1536                         string stemp = s.ToLower ();\r
1537                         string p1 = null;\r
1538                         string p2 = null;\r
1539                         string p3 = null;\r
1540 \r
1541                         s = s.Substring (stemp.IndexOf ("substring") + 9);\r
1542 \r
1543                         // find (\r
1544                         while (!s.StartsWith ("("))\r
1545                                 s = s.Remove (0, 1);\r
1546 \r
1547                         // remove (\r
1548                         s = s.Remove (0, 1);\r
1549                         int parentheses = 0;\r
1550                         for (int i = 0; i < s.Length; i++) \r
1551                         {\r
1552 \r
1553                                 if (s [i] == '\'')\r
1554                                         inString = !inString;\r
1555                                 else if (s [i] == '(')\r
1556                                         parentheses++;\r
1557                                 else if (s [i] == ')')\r
1558                                         parentheses--;\r
1559 \r
1560 \r
1561                                 if ((s [i] == ',' && !inString && parentheses == 0) || \r
1562                                         (s [i] == ')' && i == (s.Length -1))) \r
1563                                 { // Parameter changed\r
1564 \r
1565                                         if (p1 == null) \r
1566                                         {\r
1567                                                 p1 = s.Substring (0, i);\r
1568                                                 s = s.Substring (i + 1);\r
1569                                                 i = 0;\r
1570                                         }\r
1571 \r
1572                                         else if (p2 == null) \r
1573                                         {\r
1574                                                 p2 = s.Substring (0, i);\r
1575                                                 s = s.Substring (i + 1);\r
1576                                                 i = 0;\r
1577                                         }\r
1578 \r
1579                                         else if (p3 == null) \r
1580                                         {\r
1581                                                 p3 = s.Substring (0, i);\r
1582                                                 s = s.Substring (i + 1);\r
1583                                                 i = 0;\r
1584                                         }\r
1585 \r
1586                                         else\r
1587                                                 throw new Exception (); // FIXME: What exception\r
1588                                 }\r
1589                         }\r
1590 \r
1591                         if (p1 == null || p2 == null)\r
1592                                 throw new Exception ();\r
1593 \r
1594                         ParseExpression (p1);\r
1595                         ParseExpression (p2);\r
1596                         ParseExpression (p3);                   \r
1597                 }\r
1598         }\r
1599 \r
1600         /// <summary>\r
1601         ///  Class for In (exp, exp, exp, ...) function\r
1602         /// </summary>\r
1603         internal class ExpressionIn : ExpressionElement\r
1604         {\r
1605                 public ExpressionIn (string exp1, string exp2)\r
1606                 {       \r
1607                         ParseExpression(exp1);\r
1608                         ParseParameters (exp2);\r
1609                 }\r
1610 \r
1611                 /// <summary>\r
1612                 ///  IsNull function does not return boolean value, so throw exception\r
1613                 /// </summary>\r
1614                 public override bool Test (DataRow Row) \r
1615                 {\r
1616                         ExpressionElement E;\r
1617                         ExpressionElement columnElement = (ExpressionElement)Elements [0];\r
1618 \r
1619                         ExpressionElementComparer comparer = new ExpressionElementComparer(columnElement, Row);\r
1620 \r
1621                         for (int i = 1; i < Elements.Count; i++)\r
1622                         {\r
1623                                 E = (ExpressionElement)Elements [i];\r
1624                                 if(comparer.CompareTo(E) == 0)\r
1625                                         return true;\r
1626                         }\r
1627                         return false;\r
1628                 }\r
1629 \r
1630                 /// <summary>\r
1631                 ///  Parses parameters of function and invoke ParseExpression methods\r
1632                 /// </summary>\r
1633                 private void ParseParameters (string s)\r
1634                 {\r
1635                         bool inString = false;\r
1636                         ArrayList parameters = new ArrayList();\r
1637                         \r
1638                         // find (\r
1639                         while (!s.StartsWith ("("))\r
1640                                 s = s.Remove (0, 1);\r
1641 \r
1642                         // remove (\r
1643                         s = s.Remove (0, 1);\r
1644                         int parentheses = 0;\r
1645                         for (int i = 0; i < s.Length; i++) \r
1646                         {\r
1647 \r
1648                                 if (s [i] == '\'')\r
1649                                         inString = !inString;\r
1650                                 else if (s [i] == '(')\r
1651                                         parentheses++;\r
1652                                 else if (s [i] == ')')\r
1653                                         parentheses--;\r
1654 \r
1655 \r
1656                                 if ((s [i] == ',' && !inString && parentheses == 0) || \r
1657                                         (s [i] == ')' && i == (s.Length -1))) \r
1658                                 {\r
1659                                         parameters.Add(s.Substring (0, i));\r
1660                                         s = s.Substring (i + 1);\r
1661                                         i = 0;\r
1662                                 }\r
1663                         }\r
1664                         \r
1665                         for (int i = 0; i < parameters.Count; i++)\r
1666                                 ParseExpression((string)parameters[i]);\r
1667                 }\r
1668         }\r
1669 \r
1670         /// <summary>\r
1671         ///  Class for just one element for example string, int, ...\r
1672         /// </summary>\r
1673         internal class ExpressionSingleElement : ExpressionElement\r
1674         {               \r
1675                 private object Element = null;\r
1676                 \r
1677                 public ExpressionSingleElement (string s)\r
1678                 {\r
1679                         // TODO: Every type should be checked\r
1680                         if (s.StartsWith ("'") && s.EndsWith ("'")) \r
1681                         {\r
1682                                 Element = s.Substring (1, s.Length - 2);\r
1683                                 _ResultType = typeof (string);\r
1684                         }\r
1685                         else if (!Char.IsDigit (s [0]) && s [0] != '-' && s [0] != '+') \r
1686                         {\r
1687                                 Element = s;\r
1688                                 _ResultType = typeof (DataColumn);\r
1689                         }\r
1690                         else if (s.StartsWith ("#") && s.EndsWith ("#")) \r
1691                         {\r
1692                                 Element = DateTime.Parse (s.Substring (1, s.Length - 2));\r
1693                                 _ResultType = typeof (DateTime);\r
1694                         }\r
1695                         else \r
1696                         {\r
1697                                 try \r
1698                                 {\r
1699                                         Element = int.Parse (s);\r
1700                                         _ResultType = typeof (int);\r
1701                                 } \r
1702                                 catch \r
1703                                 {\r
1704                                         Element = Decimal.Parse (s);\r
1705                                         _ResultType = typeof (Decimal);\r
1706                                 }\r
1707                         }                               \r
1708                 }\r
1709 \r
1710                 public override object Result (DataRow Row)\r
1711                 {\r
1712                         object Result = null;\r
1713                         if (ResultType (Row) == typeof (DataColumn)) \r
1714                         {\r
1715                                 \r
1716                                 if (!Row.Table.Columns.Contains (Element.ToString ()))\r
1717                                         throw new EvaluateException ("Column name '" + Element.ToString () + "' not found.");\r
1718                                 else\r
1719                                 {\r
1720                                         DataRowVersion rowVersion = DataRowVersion.Default;\r
1721                                         // if this row is deleted we get the original version, or else we get an exception.\r
1722                                         if (Row.RowState == DataRowState.Deleted)\r
1723                                                 rowVersion = DataRowVersion.Original;\r
1724                                         Result = Row [Element.ToString (), rowVersion];\r
1725                                 }\r
1726                         }\r
1727                         else\r
1728                                 Result = Element;\r
1729                                 \r
1730                         return Result;\r
1731                 }\r
1732                 \r
1733                 public override bool Test (DataRow Row)\r
1734                 {\r
1735                         throw new EvaluateException ();\r
1736                 }               \r
1737         }\r
1738 \r
1739         /// <summary>\r
1740         ///  Parent class of all the elements of expression\r
1741         /// </summary>\r
1742         internal abstract class ExpressionElement\r
1743         {        \r
1744                 enum OP {OPERATOR, OPERAND};\r
1745                 enum OPERATOR_TYPE {SYMBOLIC, LITERAL, UNDEFINED};\r
1746                 enum OPERAND_TYPE {NUMERIC, STRING, UNDEFINED};\r
1747 \r
1748                 // \r
1749                 // TODO/FIXME: This class should be inherited more than once. I mean own subclass for operators, functions,...\r
1750                 //\r
1751 \r
1752                 protected string exp1;\r
1753                 protected string exp2;\r
1754                 protected  Type _ResultType;\r
1755 \r
1756                 protected ArrayList Elements = new ArrayList ();\r
1757 \r
1758                 enum AGGREGATE {SUM, AVG, MIN, MAX, COUNT, STDEV, VAR}\r
1759                 //protected ArrayList Singles = new ArrayList ();\r
1760                 \r
1761                 /// <summary>\r
1762                 /// Tells does the current expressions match to current DataRow\r
1763                 /// </summary>\r
1764                 abstract public bool Test (DataRow Row);\r
1765 \r
1766                 public virtual object Result (DataRow Row) {return null;}\r
1767                 \r
1768                 public virtual Type ResultType (DataRow Row)\r
1769                 {\r
1770                         return _ResultType;\r
1771                 }\r
1772 \r
1773                 protected object CalculateResult (DataRow Row)\r
1774                 {\r
1775                         ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
1776                         ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
1777                         object Result = null;\r
1778                         object value1 = E1.Result (Row);\r
1779                         object value2 = E2.Result (Row);\r
1780                         Type t1 = value1.GetType ();\r
1781                         Type t2 = value2.GetType ();\r
1782                         \r
1783                         // Check nulls\r
1784                         if (value1 ==  DBNull.Value && value2 == DBNull.Value)\r
1785                                 return null;\r
1786                         \r
1787                         // TODO: More types\r
1788                         \r
1789                         if (t1 == typeof (string) || t2 == typeof (string)) \r
1790                         {\r
1791                                 \r
1792                                 if (t1 != typeof (string))\r
1793                                         value1 = Convert.ChangeType (value1, Type.GetTypeCode (t2));\r
1794                                 else if (t2 != typeof (string))\r
1795                                         value2 = Convert.ChangeType (value2, Type.GetTypeCode (t1));\r
1796                         }\r
1797                         \r
1798                         if (t1 != t2)\r
1799                                 value2 = Convert.ChangeType (value2, Type.GetTypeCode (t1));\r
1800                         \r
1801                         Result = Calculate (value1, value2, t1);\r
1802                         \r
1803                         return Result; \r
1804                 }\r
1805                 protected virtual object Calculate (object value1, object value2, Type TempType)\r
1806                 {\r
1807                         return null;\r
1808                 }\r
1809                 \r
1810                 /// <summary>\r
1811                 ///  static method for comparing two ExpressionElement. This is used in =, <, >, <>, <=, >= elements.\r
1812                 ///  If elements are equal returns 0, if E1 is less that E2, return -1 else if E1 is greater 1 \r
1813                 /// </summary>\r
1814                 protected static int Compare (ExpressionElement E1, ExpressionElement E2, DataRow Row)\r
1815                 { \r
1816                         ExpressionElementComparer comparer = new ExpressionElementComparer(E1, Row);\r
1817 \r
1818                         return comparer.CompareTo(E2);\r
1819                 }\r
1820 \r
1821                 /// <summary>\r
1822                 ///  Checks syntax of expression and throws exception if needed.\r
1823                 ///  Also removes whitespaces between operator elements for example: age < = 64 --> age <= 64\r
1824                 /// </summary>\r
1825                 internal static string ValidateExpression (string s)\r
1826                 {                       \r
1827                         //\r
1828                         // TODO: find out nice way to do this. This is NOT nice way :-P\r
1829                         //\r
1830                         //string temp = "";\r
1831                         OP op = OP.OPERAND;\r
1832                         OPERATOR_TYPE operatorType = OPERATOR_TYPE.UNDEFINED;\r
1833 \r
1834                         StringBuilder strOperator = new StringBuilder();\r
1835                         StringBuilder strOperand = new StringBuilder();\r
1836                         int quotes = 0;\r
1837                         int parentheses = 0;\r
1838                         StringBuilder newExp = new StringBuilder();\r
1839                         bool isDigit = false;\r
1840                         //bool litOperator = false;\r
1841                         s = s.Trim();\r
1842                         \r
1843                         for (int i = 0; i < s.Length; i++) \r
1844                         {\r
1845 \r
1846                                 char c = s [i];\r
1847                                 \r
1848                                 if (c == '\'')\r
1849                                         quotes++;\r
1850 \r
1851                                 if ((c == '\n' || c == '\t') && quotes == 0)\r
1852                                         c = ' ';\r
1853 \r
1854                                 if (op == OP.OPERAND && c == '(')\r
1855                                         parentheses++;\r
1856                                 else if (op == OP.OPERAND && c == ')')\r
1857                                         parentheses--;\r
1858 \r
1859                                 if (c == ' ' && op ==  OP.OPERAND && (quotes % 2) == 0 && parentheses == 0) \r
1860                                 {\r
1861                                         \r
1862                                         op = OP.OPERATOR;\r
1863                                         int max = strOperand.Length;\r
1864                                         for (int it = 0; it < max; it++)\r
1865                                                 newExp.Append(strOperand[it]);\r
1866                                         strOperand.Remove(0, max);\r
1867                                         strOperator.Append(' ');\r
1868                                 }\r
1869 \r
1870                                 if (op == OP.OPERAND) \r
1871                                 {\r
1872 \r
1873                                         if (!Char.IsDigit (c) && isDigit && (quotes % 2) == 0) \r
1874                                         {\r
1875                                                 int max = strOperand.Length;\r
1876                                                 for (int it = 0; it < max; it++)\r
1877                                                         newExp.Append(strOperand[it]);\r
1878                                                 strOperand.Remove(0, max);\r
1879                                                 op = OP.OPERATOR;\r
1880                                                 operatorType = OPERATOR_TYPE.UNDEFINED;\r
1881                                         }\r
1882                                         else\r
1883                                                 strOperand.Append(c);\r
1884                                 }\r
1885 \r
1886                                 if (op == OP.OPERATOR) \r
1887                                 {\r
1888 \r
1889                                         isDigit = false;\r
1890                                         if (operatorType == OPERATOR_TYPE.UNDEFINED) \r
1891                                         {\r
1892 \r
1893                                                 if (c == '<' || c == '=' || c == '>' || c == '*' || c == '/' || c == '%' \r
1894                                                         || c == '-' || c == '+')\r
1895 \r
1896                                                         operatorType = OPERATOR_TYPE.SYMBOLIC;\r
1897                                                 else if (c != ' ')\r
1898                                                         operatorType = OPERATOR_TYPE.LITERAL;\r
1899                                         }\r
1900                                         else if (operatorType == OPERATOR_TYPE.SYMBOLIC) \r
1901                                         {\r
1902                                                 \r
1903                                                 //Checking for operators following one another\r
1904                                                 if ((c == '=' || c== '<' || c== '>') &&\r
1905                                                         (strOperator.Length == 2) &&\r
1906                                                         (strOperator[0] == ' '))\r
1907                                                 {\r
1908                                                         char chSecond = strOperator[1];\r
1909                                                         if (chSecond == '+' ||\r
1910                                                                 chSecond == '-' ||\r
1911                                                                 chSecond == '%' ||\r
1912                                                                 chSecond == '*')\r
1913                                                         throw new SyntaxErrorException (\r
1914                                                                 "The operator " + strOperator.ToString() + c + " is not valid");\r
1915                                                 }\r
1916 \r
1917                                                 // this is COPY-PASTE\r
1918                                                 op = OP.OPERAND;\r
1919                                                 if (newExp[newExp.Length - 1] != ' '  && \r
1920                                                         strOperator[0] != ' ')\r
1921                                                         newExp.Append(' ');\r
1922 \r
1923                                                 int max = strOperator.Length;\r
1924                                                 for (int it = 0; it < max; it++)\r
1925                                                         newExp.Append(strOperator[it]);\r
1926                                                 strOperator.Remove(0, max);\r
1927 \r
1928                                                 if (Char.IsDigit (c))\r
1929                                                         isDigit = true;\r
1930                                                         \r
1931                                                 strOperand.Remove(0, strOperand.Length);\r
1932                                                 strOperand.Append(c);\r
1933                                                 \r
1934                                                 continue;\r
1935 \r
1936                                         }\r
1937 \r
1938                                         if (operatorType == OPERATOR_TYPE.LITERAL && c == ' ') \r
1939                                         {\r
1940                                                 op = OP.OPERAND;\r
1941                                                 int max = strOperator.Length;\r
1942                                                 for (int it = 0; it < max; it++)\r
1943                                                         newExp.Append(strOperator[it]);\r
1944                                                 strOperator.Remove(0, max);\r
1945 \r
1946                                                 strOperand.Append(' ');\r
1947                                         }\r
1948 \r
1949 \r
1950                                         if (Char.IsDigit (c) && operatorType != OPERATOR_TYPE.LITERAL) \r
1951                                         {\r
1952 \r
1953                                                 op = OP.OPERAND;\r
1954                                                 if (newExp[newExp.Length - 1] != ' '  && \r
1955                                                         strOperator[0] != ' ')\r
1956                                                         newExp.Append(' ');\r
1957 \r
1958                                                 int max = strOperator.Length;\r
1959                                                 for (int it = 0; it < max; it++)\r
1960                                                         newExp.Append(strOperator[it]);\r
1961                                                 strOperator.Remove(0, max);\r
1962 \r
1963                                                 if (Char.IsDigit (c))\r
1964                                                         isDigit = true;\r
1965                                                         \r
1966                                                 strOperand.Remove(0, strOperand.Length);\r
1967                                                 strOperand.Append(c);\r
1968                                         }\r
1969 \r
1970                                         else if (c != ' ')\r
1971                                                 strOperator.Append(c);                                  \r
1972                                 }\r
1973                         }\r
1974 \r
1975                         if (op == OP.OPERATOR)\r
1976                                 throw new SyntaxErrorException (\r
1977                                         "Missing operand after '" + strOperator.ToString() + "' operator");\r
1978                         else\r
1979                         {\r
1980                                 int max = strOperand.Length;\r
1981                                 for (int it = 0; it < max; it++)\r
1982                                         newExp.Append(strOperand[it]);\r
1983                         }\r
1984 \r
1985                         return newExp.ToString();\r
1986                 }\r
1987 \r
1988                 /// <summary>\r
1989                 ///  Finds and creates Expression elements.\r
1990                 ///  This presumes that expression is valid.\r
1991                 /// </summary>\r
1992                 protected void ParseExpression (string s)\r
1993                 {       \r
1994                         //\r
1995                         // TODO/FIXME: IMHO, this should be done with different kind of parsing:\r
1996                         // char by char not operand by operand. \r
1997                         // fixed the easy places, should consider better parsing\r
1998                         //\r
1999 \r
2000                         string inside = String.Empty; // stores string betwee parentheses like a = 12 and (b = 1 or b = 2)\r
2001                         string lower = s.ToLower();\r
2002                         //string function = ""; // stores fuction paramters like substring (this, are, paramters)\r
2003                         //string s1 = "";\r
2004                         //string s2 = "";\r
2005                         int startIndex = lower.IndexOf ('(');\r
2006                         \r
2007                         // Find parenthesis\r
2008                         if (startIndex != -1) \r
2009                         {\r
2010                                 string functionName = String.Empty;\r
2011                                 if (startIndex > 0)\r
2012                                 {\r
2013                                         int functionStart = lower.LastIndexOf('=', startIndex-1, startIndex);\r
2014                                         if (functionStart < 0)\r
2015                                                 functionStart++;\r
2016                                         functionName = lower.Substring(functionStart, startIndex);\r
2017 \r
2018                                         functionName = functionName.Trim ();\r
2019                                 }\r
2020 \r
2021                                 // check if previous element is a function\r
2022                                 if (functionName.Length == 0 || (!functionName.EndsWith ("convert") && !functionName.EndsWith ("len") &&\r
2023                                         !functionName.EndsWith ("isnull") && !functionName.EndsWith ("iif") &&\r
2024                                         !functionName.EndsWith ("trim") && !functionName.EndsWith ("substring") &&\r
2025                                         !functionName.EndsWith ("sum") && !functionName.EndsWith ("avg") &&\r
2026                                         !functionName.EndsWith ("min") && !functionName.EndsWith ("max") &&\r
2027                                         !functionName.EndsWith ("count") && !functionName.EndsWith ("stdev") &&\r
2028                                         !functionName.EndsWith ("var")&& !functionName.EndsWith ("in"))) \r
2029                                 {\r
2030                                         \r
2031                                         \r
2032                                         int i = startIndex + 1;\r
2033                                         int max = lower.Length;\r
2034                         \r
2035                                         for (int par = 1; par > 0 && i < max; i++) \r
2036                                         {\r
2037 \r
2038                                                 char c = s [i];\r
2039                                                 if (c == '(')\r
2040                                                         par++;\r
2041                                                 else\r
2042                                                 if (c == ')')\r
2043                                                         par--;\r
2044                                         }\r
2045                                         \r
2046                                         inside = s.Substring(startIndex + 1, i - startIndex - 2); \r
2047                                         lower = lower.Remove (startIndex, i - startIndex);\r
2048                                         s = s.Remove (startIndex, i - startIndex);\r
2049                                 }               \r
2050                                              \r
2051                         }\r
2052                         \r
2053                         string string1 = null;\r
2054                         string string2 = null;\r
2055                         if (FindOrElement (s, lower, ref string1, ref string2))         \r
2056                                 CreateOrElement (string1, string2, inside);\r
2057 \r
2058                         else if (FindAndElement (s, lower, ref string1, ref string2))\r
2059                                 CreateAndElement (string1, string2, inside);\r
2060 \r
2061                                 // find LIKE\r
2062                         else if (FindLikeElement (s, lower, ref string1, ref string2))\r
2063                                 CreateLikeElement (string1, string2, inside);\r
2064                         \r
2065                                 // find IN\r
2066                         else if (FindInElement (s, lower, ref string1, ref string2))\r
2067                                 CreateInElement (string1, string2, inside);\r
2068 \r
2069                                 // find =\r
2070                         else if (FindEqualElement (s, lower, ref string1, ref string2))\r
2071                                 CreateEqualsElement (string1, string2, inside);\r
2072 \r
2073                                 // find <>\r
2074                         else if (FindUnequalElement (s, lower, ref string1, ref string2))\r
2075                                 CreateUnequalsElement (string1, string2, inside);\r
2076 \r
2077                                 // find <=\r
2078                         else if (FindLessThanOrEqualElement (s, lower, ref string1, ref string2))\r
2079                                 CreateLessThanOrEqualElement (string1, string2, inside);\r
2080 \r
2081                                 // find <\r
2082                         else if (FindLessThanElement (s, lower, ref string1, ref string2))\r
2083                                 CreateLessThanElement (string1, string2, inside);\r
2084 \r
2085                                 // find >=\r
2086                         else if (FindGreaterThanOrEqualElement (s, lower, ref string1, ref string2))\r
2087                                 CreateGreaterThanOrEqualElement (string1, string2, inside);\r
2088 \r
2089                                 // find >\r
2090                         else if (FindGreaterThanElement (s, lower, ref string1, ref string2))\r
2091                                 CreateGreaterThanElement (string1, string2,  inside);\r
2092 \r
2093                                 // if there wasn't any operators like 'and' or 'not' there still could be\r
2094                                 // arithmetic operators like '+' or '-' or functions like 'iif' or 'substring'\r
2095 \r
2096                                 // find *\r
2097                         else if (FindMultiplyElement (s, lower, ref string1, ref string2))\r
2098                                 CreateMultiplyElement (string1, string2, inside);\r
2099                         \r
2100                                 // find /\r
2101                         else if (FindDivideElement (s, lower, ref string1, ref string2))\r
2102                                 CreateDivideElement (string1, string2, inside);\r
2103 \r
2104 \r
2105                                 // find +\r
2106                         else if (FindAdditionElement (s, lower, ref string1, ref string2))\r
2107                                 CreateAdditionElement (string1, string2, inside);\r
2108 \r
2109                                 // find -\r
2110                         else if (FindSubtractElement (s, lower, ref string1, ref string2))\r
2111                                 CreateSubtractionElement (string1, string2, inside);\r
2112 \r
2113                                 // find %\r
2114                         else if (FindModulusElement (s, lower, ref string1, ref string2))\r
2115                                 CreateModulusElement (string1, string2, inside);\r
2116 \r
2117                                 // find sum ()\r
2118                         else if (FindAggregateElement (s, lower, AGGREGATE.SUM))\r
2119                                 Elements.Add (new ExpressionSum (s.Trim ()));\r
2120 \r
2121                                 // find avg ()\r
2122                         else if (FindAggregateElement (s, lower, AGGREGATE.AVG))\r
2123                                 Elements.Add (new ExpressionAvg (s.Trim ()));\r
2124 \r
2125                                 // find min ()\r
2126                         else if (FindAggregateElement (s, lower, AGGREGATE.MIN))\r
2127                                 Elements.Add (new ExpressionMin (s.Trim ()));\r
2128 \r
2129                                 // find max ()\r
2130                         else if (FindAggregateElement (s, lower, AGGREGATE.MAX))\r
2131                                 Elements.Add (new ExpressionMax (s.Trim ()));\r
2132 \r
2133                                 // find count ()\r
2134                         else if (FindAggregateElement (s, lower, AGGREGATE.COUNT))\r
2135                                 Elements.Add (new ExpressionCount (s.Trim ()));                            \r
2136 \r
2137                                 // find stdev ()\r
2138                         else if (FindAggregateElement (s, lower, AGGREGATE.STDEV))\r
2139                                 Elements.Add (new ExpressionStdev (s.Trim ()));\r
2140 \r
2141                                 // find var ()\r
2142                         else if (FindAggregateElement (s, lower, AGGREGATE.VAR))\r
2143                                 Elements.Add (new ExpressionVar (s.Trim ()));\r
2144 \r
2145                                 // find len\r
2146                         else if (FindLenElement (s, lower))\r
2147                                 Elements.Add (new ExpressionLen (s.Trim ()));\r
2148 \r
2149                                 // find iif\r
2150                         else if (FindIifElement (s, lower))\r
2151                                 Elements.Add (new ExpressionIif (s.Trim ()));\r
2152 \r
2153                                 // find isnull\r
2154                         else if (FindIsNullElement (s, lower))\r
2155                                 Elements.Add (new ExpressionIsNull (s.Trim ()));\r
2156 \r
2157                                 // find substring\r
2158                         else if (FindSubstringElement (s, lower))\r
2159                                 Elements.Add (new ExpressionSubstring (s.Trim ()));\r
2160 \r
2161                                 // if expression is like '(something someoperator something)'\r
2162                         else if (inside.Trim () != string.Empty)\r
2163                                 ParseExpression (inside);\r
2164 \r
2165                                 // At least, if it wasnt any of the above it is just normat string or int\r
2166                                 // or....                       \r
2167                         else\r
2168                                 Elements.Add (new ExpressionSingleElement (s.Trim ()));                 \r
2169                 }\r
2170 \r
2171                 #region CheckElement methods\r
2172 \r
2173                 //\r
2174                 // These methods are temporary for now\r
2175                 //\r
2176 \r
2177                 private bool FindOrElement (string s, string lower, ref string s1, ref string s2)\r
2178                 {\r
2179                         string stemp = lower;\r
2180                         int indexOf = stemp.IndexOf("or");\r
2181 \r
2182                         if (indexOf == -1)\r
2183                                 return false;\r
2184 \r
2185                         // Test if or is between ''\r
2186                         int oldIndex = -1;                      \r
2187                         while ((indexOf = stemp.IndexOf ("or", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2188                         {\r
2189                                 \r
2190                                 oldIndex = indexOf;\r
2191 \r
2192                                 // check is the 'or' element part of string element\r
2193                                 if (IsPartOfStringElement (stemp, indexOf))\r
2194                                         continue;\r
2195                                 \r
2196                                 // Check is or part of something else for example column name\r
2197                                 if (indexOf != 0) \r
2198                                 {\r
2199                                         \r
2200                                         if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
2201                                                 continue;\r
2202                                 }\r
2203                                 \r
2204                                 if (indexOf < s.Length + 2) \r
2205                                 {\r
2206                                         \r
2207                                         if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')\r
2208                                                 continue;\r
2209                                 }\r
2210 \r
2211                                 if (IsPartOfFunction (stemp, indexOf))\r
2212                                         continue;\r
2213 \r
2214                                 s1 = s.Substring (0, indexOf).Trim ();\r
2215                                 s2 = s.Substring (indexOf + 2).Trim ();\r
2216 \r
2217                                 return true;\r
2218                         }\r
2219 \r
2220                         return false;\r
2221                 }\r
2222                 \r
2223                 private bool FindAndElement (string s, string lower, ref string s1, ref string s2)\r
2224                 {\r
2225                         string stemp = lower;\r
2226                         int indexOf = stemp.IndexOf("and");\r
2227 \r
2228                         if (indexOf == -1)\r
2229                                 return false;\r
2230 \r
2231                         // Test if or is between ''\r
2232                         int oldIndex = -1;\r
2233                         while ((indexOf = stemp.IndexOf ("and", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2234                         {\r
2235                                 \r
2236                                 oldIndex = indexOf;\r
2237                                 \r
2238                                 // check is the 'and' element part of string element\r
2239                                 if (IsPartOfStringElement (stemp, indexOf))\r
2240                                         continue;\r
2241 \r
2242 \r
2243                                 // Check is or part of something else for example column name\r
2244                                 if (indexOf != 0) \r
2245                                 {\r
2246                                         \r
2247                                         if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
2248                                                 continue;\r
2249                                 }\r
2250                                 \r
2251                                 if (indexOf < stemp.Length + 3) \r
2252                                 {\r
2253                                         \r
2254                                         if (stemp [indexOf + 3] != ' ' && stemp [indexOf + 3] != '\'')\r
2255                                                 continue;\r
2256                                 }\r
2257 \r
2258                                 if (IsPartOfFunction (stemp, indexOf))\r
2259                                         continue;\r
2260 \r
2261 \r
2262                                 s1 = s.Substring (0, indexOf).Trim ();\r
2263                                 s2 = s.Substring (indexOf + 3).Trim ();\r
2264                                 return true;\r
2265                         }\r
2266 \r
2267                         return false;\r
2268                 }\r
2269 \r
2270                 private bool FindLikeElement (string s, string lower, ref string s1, ref string s2)\r
2271                 {\r
2272                         string stemp = lower;\r
2273                         int indexOf = stemp.IndexOf("like");\r
2274 \r
2275                         if (indexOf == -1)\r
2276                                 return false;\r
2277 \r
2278                         // Test if or is between ''\r
2279                         int oldIndex = -1;\r
2280                         while ((indexOf = stemp.IndexOf ("like", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2281                         {\r
2282                                 \r
2283                                 oldIndex = indexOf;\r
2284                                 \r
2285                                 // check is the 'and' element part of string element\r
2286                                 if (IsPartOfStringElement (stemp, indexOf))\r
2287                                         continue;\r
2288 \r
2289 \r
2290                                 // Check is or part of something else for example column name\r
2291                                 if (indexOf != 0) \r
2292                                 {\r
2293                                         \r
2294                                         if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
2295                                                 continue;\r
2296                                 }\r
2297                                 \r
2298                                 if (indexOf < stemp.Length + 4) \r
2299                                 {\r
2300                                         \r
2301                                         if (stemp [indexOf + 4] != ' ' && stemp [indexOf + 4] != '\'')\r
2302                                                 continue;\r
2303                                 }\r
2304 \r
2305                                 if (IsPartOfFunction (stemp, indexOf))\r
2306                                         continue;\r
2307 \r
2308 \r
2309                                 s1 = s.Substring (0, indexOf).Trim ();\r
2310                                 s2 = s.Substring (indexOf + 4).Trim ();\r
2311                                 return true;\r
2312                         }\r
2313 \r
2314                         return false;\r
2315                 }\r
2316 \r
2317                 private bool FindEqualElement (string s, string lower, ref string s1, ref string s2)\r
2318                 {\r
2319                         string stemp = lower;\r
2320                         int indexOf = stemp.IndexOf ("=");\r
2321 \r
2322                         if (indexOf == -1)\r
2323                                 return false;\r
2324                         \r
2325                         int oldIndex = -1;\r
2326 \r
2327                         while ((indexOf = stemp.IndexOf ("=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2328                         {\r
2329 \r
2330                                 oldIndex = indexOf;\r
2331 \r
2332                                 // Check is the = part of <= or >=\r
2333                                 if (stemp [indexOf - 1] == '<' || stemp [indexOf - 1] == '>')\r
2334                                         continue;\r
2335 \r
2336                                 // Check is the = element part of string element\r
2337                                 if (IsPartOfStringElement (stemp, indexOf))\r
2338                                         continue;\r
2339 \r
2340                                 // Check is or part of column name\r
2341                                 if (IsPartOfColumnName (stemp, indexOf))\r
2342                                         continue;\r
2343                                         \r
2344                                 if (IsPartOfFunction (stemp, indexOf))\r
2345                                         continue;\r
2346 \r
2347                                 s1 = s.Substring (0, indexOf).Trim ();\r
2348                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2349                                 \r
2350                                 return true;\r
2351                         }\r
2352 \r
2353                         return false;\r
2354                 }\r
2355 \r
2356                 private bool FindUnequalElement (string s, string lower, ref string s1, ref string s2)\r
2357                 {\r
2358                         string stemp = lower;\r
2359                         int indexOf = stemp.IndexOf ("<>");\r
2360 \r
2361                         if (stemp.IndexOf ("<>") == -1)\r
2362                                 return false;\r
2363                        \r
2364                         int oldIndex = -1;\r
2365                         while ((indexOf = stemp.IndexOf ("<>", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2366                         {\r
2367 \r
2368                                 oldIndex = indexOf;\r
2369 \r
2370                                 // test if next charachter is something else than ' '\r
2371                                 bool failed = false;\r
2372 \r
2373                                 // Check is the <> element part of string element\r
2374                                 if (IsPartOfStringElement (stemp, indexOf))\r
2375                                         continue;\r
2376 \r
2377                                 // Check is or part of column name\r
2378                                 if (IsPartOfColumnName (stemp, indexOf))\r
2379                                         continue;\r
2380                                         \r
2381                                 if (IsPartOfFunction (stemp, indexOf))\r
2382                                         continue;\r
2383 \r
2384                                 s1 = s.Substring (0, indexOf).Trim ();\r
2385                                 s2 = s.Substring (indexOf + 2).Trim ();\r
2386                                 \r
2387                                 return true;\r
2388                         }\r
2389 \r
2390                         return false;\r
2391                         \r
2392                 }\r
2393 \r
2394 \r
2395                 private bool FindLessThanElement (string s, string lower, ref string s1, ref string s2)\r
2396                 {\r
2397                         string stemp = lower;\r
2398                         int indexOf = stemp.IndexOf ("<");\r
2399 \r
2400                         if (indexOf == -1)\r
2401                                 return false;\r
2402 \r
2403                         int oldIndex = -1;\r
2404                         while ((indexOf = stemp.IndexOf ("<", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2405                         {\r
2406 \r
2407                                 oldIndex = indexOf;\r
2408 \r
2409                                 // if < is part of <> or <=\r
2410                                 if (stemp [indexOf + 1] == '>' || stemp [indexOf + 1] == '=')\r
2411                                         continue;\r
2412 \r
2413                                 // Test is < element part of string element\r
2414                                 if (IsPartOfStringElement (stemp, indexOf))\r
2415                                         continue;\r
2416 \r
2417                                 // Check is or part of column name\r
2418                                 if (IsPartOfColumnName (stemp, indexOf))\r
2419                                         continue;\r
2420 \r
2421                                 if (IsPartOfFunction (stemp, indexOf))\r
2422                                         continue;\r
2423 \r
2424                                 s1 = s.Substring (0, indexOf).Trim ();\r
2425                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2426 \r
2427                                 return true;\r
2428                         }\r
2429                 \r
2430                         return false;                   \r
2431                 }\r
2432 \r
2433                 private bool FindLessThanOrEqualElement (string s, string lower, ref string s1, ref string s2)\r
2434                 {\r
2435                         string stemp = lower;\r
2436                         int indexOf = stemp.IndexOf ("<=");\r
2437 \r
2438                         if (indexOf == -1)\r
2439                                 return false;\r
2440 \r
2441                         int oldIndex = -1;\r
2442                         while ((indexOf = stemp.IndexOf ("<=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2443                         {\r
2444 \r
2445                                 oldIndex = indexOf;\r
2446                                 // Test is <= element part of string element\r
2447                                 if (IsPartOfStringElement (stemp, indexOf))\r
2448                                         continue;\r
2449 \r
2450                                 // Check is or part of column name\r
2451                                 if (IsPartOfColumnName (stemp, indexOf))\r
2452                                         continue;\r
2453 \r
2454                                 if (IsPartOfFunction (stemp, indexOf))\r
2455                                         continue;\r
2456 \r
2457                                 s1 = s.Substring (0, indexOf).Trim ();\r
2458                                 s2 = s.Substring (indexOf + 2).Trim ();\r
2459 \r
2460                                 return true;\r
2461                         }\r
2462                 \r
2463                         return false;                   \r
2464                 }\r
2465 \r
2466                 private bool FindGreaterThanElement (string s, string lower, ref string s1, ref string s2)\r
2467                 {\r
2468                         string stemp = lower;\r
2469                         int indexOf = stemp.IndexOf (">");\r
2470 \r
2471                         if (indexOf == -1)\r
2472                                 return false;\r
2473 \r
2474                         int oldIndex = -1;\r
2475                         while ((indexOf = stemp.IndexOf (">", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2476                         {\r
2477 \r
2478                                 oldIndex = indexOf;\r
2479 \r
2480                                 // if < is part of <> or <=\r
2481                                 if (stemp [indexOf - 1] == '<' || stemp [indexOf + 1] == '=')\r
2482                                         continue;\r
2483 \r
2484                                 // Test is < element part of string element\r
2485                                 if (IsPartOfStringElement (stemp, indexOf))\r
2486                                         continue;\r
2487 \r
2488                                 // Check is or part of column name\r
2489                                 if (IsPartOfColumnName (stemp, indexOf))\r
2490                                         continue;\r
2491 \r
2492                                 if (IsPartOfFunction (stemp, indexOf))\r
2493                                         continue;\r
2494 \r
2495                                 s1 = s.Substring (0, indexOf).Trim ();\r
2496                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2497                                 return true;\r
2498                         }\r
2499                 \r
2500                         return false;                   \r
2501                 }\r
2502 \r
2503                 private bool FindGreaterThanOrEqualElement (string s, string lower, ref string s1, ref string s2)\r
2504                 {\r
2505                         string stemp = lower;\r
2506                         int indexOf = stemp.IndexOf (">=");\r
2507 \r
2508                         if (indexOf == -1)\r
2509                                 return false;\r
2510 \r
2511                         int oldIndex = -1;\r
2512                         while ((indexOf = stemp.IndexOf (">=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2513                         {\r
2514 \r
2515                                 oldIndex = indexOf;\r
2516                                 bool failed = false;\r
2517                                 // Test is <= element part of string element\r
2518 \r
2519                                 // Check is or part of column name\r
2520                                 if (IsPartOfColumnName (stemp, indexOf))\r
2521                                         continue;\r
2522 \r
2523                                 // is the element part of string element\r
2524                                 if (IsPartOfStringElement (stemp, indexOf))\r
2525                                         continue;\r
2526 \r
2527                                 if (IsPartOfFunction (stemp, indexOf))\r
2528                                         continue;\r
2529 \r
2530                                 s1 = s.Substring (0, indexOf).Trim ();\r
2531                                 s2 = s.Substring (indexOf + 2).Trim ();\r
2532 \r
2533                                 return true;\r
2534                         }\r
2535                 \r
2536                         return false;                   \r
2537                 }\r
2538 \r
2539                 private bool FindAdditionElement (string s, string lower, ref string s1, ref string s2)\r
2540                 {\r
2541                         string stemp = lower;\r
2542                         int indexOf = stemp.IndexOf ("+");\r
2543 \r
2544                         if (indexOf == -1)\r
2545                                 return false;\r
2546 \r
2547                         int oldIndex = -1;\r
2548                         while ((indexOf = stemp.IndexOf ("+", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2549                         {\r
2550 \r
2551                                 // FIXME: if '+' represents sign of integer\r
2552 \r
2553                                 oldIndex = indexOf;\r
2554                                 bool failed = false;\r
2555 \r
2556                                 // Check is or part of column name\r
2557                                 if (IsPartOfColumnName (stemp, indexOf))\r
2558                                         continue;\r
2559 \r
2560                                 // is the element part of string element\r
2561                                 if (IsPartOfStringElement (stemp, indexOf))\r
2562                                         continue;\r
2563 \r
2564                                 if (IsPartOfFunction (stemp, indexOf))\r
2565                                         continue;\r
2566 \r
2567                                 s1 = s.Substring (0, indexOf).Trim ();\r
2568                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2569 \r
2570                                 return true;\r
2571                         }\r
2572                 \r
2573                         return false;                   \r
2574                 }\r
2575 \r
2576                 private bool FindSubtractElement (string s, string lower, ref string s1, ref string s2)\r
2577                 {\r
2578                         string stemp = lower;\r
2579                         int indexOf = stemp.IndexOf ("-");\r
2580 \r
2581                         if (indexOf == -1)\r
2582                                 return false;\r
2583 \r
2584                         int oldIndex = -1;\r
2585                         while ((indexOf = stemp.IndexOf ("-", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2586                         {\r
2587 \r
2588                                 oldIndex = indexOf;\r
2589                                 bool failed = false;\r
2590 \r
2591                                 // check is this lonely element         \r
2592                                 failed = true;\r
2593                                 for (int i = indexOf - 1; i >= 0; i--) \r
2594                                 {\r
2595                                         if (stemp [i] != ' ') \r
2596                                         {\r
2597                                                 failed = false;\r
2598                                                 break;\r
2599                                         }\r
2600                                 }\r
2601                                         \r
2602                                 if (failed)\r
2603                                         continue;\r
2604 \r
2605                                 // Check is or part of column name\r
2606                                 if (IsPartOfColumnName (stemp, indexOf))\r
2607                                         continue;\r
2608 \r
2609                                 // is the element part of string element\r
2610                                 if (IsPartOfStringElement (stemp, indexOf))\r
2611                                         continue;\r
2612 \r
2613                                 if (IsPartOfFunction (stemp, indexOf))\r
2614                                         continue;\r
2615 \r
2616                                 s1 = s.Substring (0, indexOf).Trim ();\r
2617                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2618 \r
2619                                 return true;\r
2620                         }\r
2621                 \r
2622                         return false;                   \r
2623                 }\r
2624 \r
2625                 private bool FindMultiplyElement (string s, string lower, ref string s1, ref string s2)\r
2626                 {\r
2627                         string stemp = lower;\r
2628                         int indexOf = stemp.IndexOf ("*");\r
2629 \r
2630                         if (indexOf == -1)\r
2631                                 return false;\r
2632 \r
2633                         int oldIndex = -1;\r
2634                         while ((indexOf = stemp.IndexOf ("*", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2635                         {\r
2636 \r
2637 \r
2638                                 oldIndex = indexOf;\r
2639                                 bool failed = false;\r
2640 \r
2641                                 // FIXME: If there is a divide operator before multiply operator.\r
2642 \r
2643                                 // Check is or part of column name\r
2644                                 if (IsPartOfColumnName (stemp, indexOf))\r
2645                                         continue;\r
2646 \r
2647                                 // is the element part of string element\r
2648                                 if (IsPartOfStringElement (stemp, indexOf))\r
2649                                         continue;\r
2650 \r
2651                                 if (IsPartOfFunction (stemp, indexOf))\r
2652                                         continue;\r
2653 \r
2654                                 s1 = s.Substring (0, indexOf).Trim ();\r
2655                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2656 \r
2657                                 return true;\r
2658                         }\r
2659                 \r
2660                         return false;                   \r
2661                 }\r
2662 \r
2663                 private bool FindDivideElement (string s, string lower, ref string s1, ref string s2)\r
2664                 {\r
2665                         string stemp = lower;\r
2666                         int indexOf = stemp.IndexOf ("/");\r
2667 \r
2668                         if (indexOf == -1)\r
2669                                 return false;\r
2670 \r
2671                         int oldIndex = -1;\r
2672                         while ((indexOf = stemp.IndexOf ("/", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2673                         {\r
2674 \r
2675 \r
2676                                 oldIndex = indexOf;\r
2677                                 bool failed = false;\r
2678 \r
2679                                 // FIXME: If there is a multiply operator before divide operator.\r
2680 \r
2681                                 // Check is or part of column name\r
2682                                 if (IsPartOfColumnName (stemp, indexOf))\r
2683                                         continue;\r
2684 \r
2685                                 // is the element part of string element\r
2686                                 if (IsPartOfStringElement (stemp, indexOf))\r
2687                                         continue;\r
2688 \r
2689                                 if (IsPartOfFunction (stemp, indexOf))\r
2690                                         continue;\r
2691                                     \r
2692                                 s1 = s.Substring (0, indexOf).Trim ();\r
2693                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2694 \r
2695                                 return true;\r
2696                         }\r
2697                 \r
2698                         return false;                   \r
2699                 }\r
2700 \r
2701                 private bool FindModulusElement (string s, string lower, ref string s1, ref string s2)\r
2702                 {\r
2703                         string stemp = lower;\r
2704                         int indexOf = stemp.IndexOf ("%");\r
2705 \r
2706                         if (indexOf == -1)\r
2707                                 return false;\r
2708 \r
2709                         int oldIndex = -1;\r
2710                         while ((indexOf = stemp.IndexOf ("%", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2711                         {\r
2712 \r
2713 \r
2714                                 oldIndex = indexOf;\r
2715                                 bool failed = false;\r
2716 \r
2717                                 // FIXME: If there is a multiply operator before divide operator.\r
2718 \r
2719                                 // Check is or part of column name\r
2720                                 if (IsPartOfColumnName (stemp, indexOf))\r
2721                                         continue;\r
2722 \r
2723                                 // is the element part of string element\r
2724                                 if (IsPartOfStringElement (stemp, indexOf))\r
2725                                         continue;\r
2726 \r
2727                                 s1 = s.Substring (0, indexOf).Trim ();\r
2728                                 s2 = s.Substring (indexOf + 1).Trim ();\r
2729 \r
2730                                 return true;\r
2731                         }\r
2732                 \r
2733                         return false;                   \r
2734                 }\r
2735 \r
2736                 private bool FindAggregateElement (string s, string lower, AGGREGATE aggregate)\r
2737                 {\r
2738                         string agg = null;\r
2739 \r
2740                         switch (aggregate) \r
2741                         {\r
2742 \r
2743                                 case AGGREGATE.SUM:\r
2744                                         agg = "sum";\r
2745                                         break;\r
2746                                 case AGGREGATE.AVG:\r
2747                                         agg = "avg";\r
2748                                         break;\r
2749                                 case AGGREGATE.MIN:\r
2750                                         agg = "min";\r
2751                                         break;\r
2752                                 case AGGREGATE.MAX:\r
2753                                         agg = "max";\r
2754                                         break;\r
2755                                 case AGGREGATE.COUNT:\r
2756                                         agg = "count";\r
2757                                         break;\r
2758                                 case AGGREGATE.STDEV:\r
2759                                         agg = "stdev";\r
2760                                         break;\r
2761                                 case AGGREGATE.VAR:\r
2762                                         agg = "var";\r
2763                                         break;\r
2764                                 default:\r
2765                                         throw new NotImplementedException ();\r
2766                         }\r
2767                                \r
2768                                 \r
2769                         string stemp = lower;\r
2770                         int indexOf = stemp.IndexOf (agg);\r
2771 \r
2772                         if (indexOf == -1)\r
2773                                 return false;\r
2774 \r
2775                         int oldIndex = -1;\r
2776                         while ((indexOf = stemp.IndexOf (agg, oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2777                         {\r
2778 \r
2779                                 oldIndex = indexOf;\r
2780                                 bool failed = false;\r
2781 \r
2782                                 // Check is or part of column name\r
2783                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2784                                         continue;\r
2785 \r
2786                                 // is the element part of string element\r
2787                                 if (IsPartOfStringElement (stemp, indexOf))\r
2788                                         continue;\r
2789 \r
2790 \r
2791                                 return true;\r
2792                         }\r
2793                 \r
2794                         return false;                   \r
2795 \r
2796                 }\r
2797                 \r
2798                 private bool FindSumElement (string s, string lower)\r
2799                 {\r
2800                         string stemp = lower;\r
2801                         int indexOf = stemp.IndexOf ("sum");\r
2802 \r
2803                         if (indexOf == -1)\r
2804                                 return false;\r
2805 \r
2806                         int oldIndex = -1;\r
2807                         while ((indexOf = stemp.IndexOf ("sum", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2808                         {\r
2809 \r
2810                                 oldIndex = indexOf;\r
2811                                 bool failed = false;\r
2812 \r
2813                                 // Check is or part of column name\r
2814                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2815                                         continue;\r
2816 \r
2817                                 // is the element part of string element\r
2818                                 if (IsPartOfStringElement (stemp, indexOf))\r
2819                                         continue;\r
2820 \r
2821 \r
2822                                 return true;\r
2823                         }\r
2824                 \r
2825                         return false;                   \r
2826                 }\r
2827 \r
2828                 private bool FindAvgElement (string s, string lower)\r
2829                 {\r
2830                         string stemp = lower;\r
2831                         int indexOf = stemp.IndexOf ("avg");\r
2832 \r
2833                         if (indexOf == -1)\r
2834                                 return false;\r
2835 \r
2836                         int oldIndex = -1;\r
2837                         while ((indexOf = stemp.IndexOf ("avg", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2838                         {\r
2839 \r
2840                                 oldIndex = indexOf;\r
2841                                 bool failed = false;\r
2842 \r
2843                                 // Check is or part of column name\r
2844                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2845                                         continue;\r
2846 \r
2847                                 // is the element part of string element\r
2848                                 if (IsPartOfStringElement (stemp, indexOf))\r
2849                                         continue;\r
2850 \r
2851                                 return true;\r
2852                         }\r
2853                 \r
2854                         return false;                   \r
2855                 }\r
2856 \r
2857                 private bool FindMinElement (string s, string lower)\r
2858                 {\r
2859                         string stemp = lower;\r
2860                         int indexOf = stemp.IndexOf ("min");\r
2861 \r
2862                         if (indexOf == -1)\r
2863                                 return false;\r
2864 \r
2865                         int oldIndex = -1;\r
2866                         while ((indexOf = stemp.IndexOf ("min", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2867                         {\r
2868 \r
2869                                 oldIndex = indexOf;\r
2870                                 bool failed = false;\r
2871 \r
2872                                 // Check is or part of column name\r
2873                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2874                                         continue;\r
2875 \r
2876                                 // is the element part of string element\r
2877                                 if (IsPartOfStringElement (stemp, indexOf))\r
2878                                         continue;\r
2879 \r
2880                                 return true;\r
2881                         }\r
2882                 \r
2883                         return false;                   \r
2884                 }\r
2885 \r
2886                 private bool FindMaxElement (string s, string lower)\r
2887                 {\r
2888                         string stemp = lower;\r
2889                         int indexOf = stemp.IndexOf ("max");\r
2890 \r
2891                         if (indexOf == -1)\r
2892                                 return false;\r
2893 \r
2894                         int oldIndex = -1;\r
2895                         while ((indexOf = stemp.IndexOf ("max", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2896                         {\r
2897 \r
2898                                 oldIndex = indexOf;\r
2899                                 bool failed = false;\r
2900 \r
2901                                 // Check is or part of column name\r
2902                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2903                                         continue;\r
2904 \r
2905                                 // is the element part of string element\r
2906                                 if (IsPartOfStringElement (stemp, indexOf))\r
2907                                         continue;\r
2908 \r
2909                                 return true;\r
2910                         }\r
2911                 \r
2912                         return false;                   \r
2913                 }\r
2914 \r
2915                 private bool FindCountElement (string s, string lower)\r
2916                 {\r
2917                         string stemp = lower;\r
2918                         int indexOf = stemp.IndexOf ("count");\r
2919 \r
2920                         if (indexOf == -1)\r
2921                                 return false;\r
2922 \r
2923                         int oldIndex = -1;\r
2924                         while ((indexOf = stemp.IndexOf ("count", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2925                         {\r
2926 \r
2927                                 oldIndex = indexOf;\r
2928                                 bool failed = false;\r
2929 \r
2930                                 // Check is or part of column name\r
2931                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2932                                         continue;\r
2933 \r
2934                                 // is the element part of string element\r
2935                                 if (IsPartOfStringElement (stemp, indexOf))\r
2936                                         continue;\r
2937 \r
2938                                 return true;\r
2939                         }\r
2940                 \r
2941                         return false;                   \r
2942                 }\r
2943 \r
2944                 private bool FindStdevElement (string s, string lower)\r
2945                 {\r
2946                         string stemp = lower;\r
2947                         int indexOf = stemp.IndexOf ("stdev");\r
2948 \r
2949                         if (indexOf == -1)\r
2950                                 return false;\r
2951 \r
2952                         int oldIndex = -1;\r
2953                         while ((indexOf = stemp.IndexOf ("stdev", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2954                         {\r
2955 \r
2956                                 oldIndex = indexOf;\r
2957                                 bool failed = false;\r
2958 \r
2959                                 // Check is or part of column name\r
2960                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2961                                         continue;\r
2962 \r
2963                                 // is the element part of string element\r
2964                                 if (IsPartOfStringElement (stemp, indexOf))\r
2965                                         continue;\r
2966 \r
2967                                 return true;\r
2968                         }\r
2969                 \r
2970                         return false;                   \r
2971                 }\r
2972 \r
2973                 private bool FindVarElement (string s, string lower)\r
2974                 {\r
2975                         string stemp = lower;\r
2976                         int indexOf = stemp.IndexOf ("var");\r
2977 \r
2978                         if (indexOf == -1)\r
2979                                 return false;\r
2980 \r
2981                         int oldIndex = -1;\r
2982                         while ((indexOf = stemp.IndexOf ("var", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
2983                         {\r
2984 \r
2985                                 oldIndex = indexOf;\r
2986                                 bool failed = false;\r
2987 \r
2988                                 // Check is or part of column name\r
2989                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
2990                                         continue;\r
2991 \r
2992                                 // is the element part of string element\r
2993                                 if (IsPartOfStringElement (stemp, indexOf))\r
2994                                         continue;\r
2995 \r
2996                                 return true;\r
2997                         }\r
2998                 \r
2999                         return false;                   \r
3000                 }\r
3001 \r
3002                 private bool FindLenElement (string s, string lower)\r
3003                 {\r
3004                         string stemp = lower;\r
3005                         int indexOf = stemp.IndexOf ("len");\r
3006 \r
3007                         if (indexOf == -1)\r
3008                                 return false;\r
3009 \r
3010                         int oldIndex = -1;\r
3011                         while ((indexOf = stemp.IndexOf ("len", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
3012                         {\r
3013 \r
3014                                 oldIndex = indexOf;\r
3015                                 bool failed = false;\r
3016 \r
3017                                 // Check is or part of column name\r
3018                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
3019                                         continue;\r
3020 \r
3021                                 // is the element part of string element\r
3022                                 if (IsPartOfStringElement (stemp, indexOf))\r
3023                                         continue;\r
3024 \r
3025 \r
3026                                 return true;\r
3027                         }\r
3028                 \r
3029                         return false;                   \r
3030                 }\r
3031 \r
3032                 private bool FindIifElement (string s, string lower)\r
3033                 {\r
3034                         string stemp = lower;\r
3035                         int indexOf = stemp.IndexOf ("iif");\r
3036 \r
3037                         if (indexOf == -1)\r
3038                                 return false;\r
3039 \r
3040                         int oldIndex = -1;\r
3041                         while ((indexOf = stemp.IndexOf ("iif", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
3042                         {\r
3043 \r
3044                                 oldIndex = indexOf;\r
3045                                 bool failed = false;\r
3046 \r
3047                                 // Check is or part of column name\r
3048                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
3049                                         continue;\r
3050 \r
3051                                 // is the element part of string element\r
3052                                 if (IsPartOfStringElement (stemp, indexOf))\r
3053                                         continue;\r
3054 \r
3055                                 return true;\r
3056                         }\r
3057                 \r
3058                         return false;                   \r
3059                 }\r
3060 \r
3061                 private bool FindIsNullElement (string s, string lower)\r
3062                 {\r
3063                         string stemp = lower;\r
3064                         int indexOf = stemp.IndexOf ("isnull");\r
3065 \r
3066                         if (indexOf == -1)\r
3067                                 return false;\r
3068 \r
3069                         int oldIndex = -1;\r
3070                         while ((indexOf = stemp.IndexOf ("isnull", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
3071                         {\r
3072 \r
3073                                 oldIndex = indexOf;\r
3074                                 bool failed = false;\r
3075 \r
3076                                 // Check is or part of column name\r
3077                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
3078                                         continue;\r
3079 \r
3080                                 // is the element part of string element\r
3081                                 if (IsPartOfStringElement (stemp, indexOf))\r
3082                                         continue;\r
3083                                 \r
3084                                 return true;\r
3085                         }\r
3086                 \r
3087                         return false;                   \r
3088                 }\r
3089 \r
3090                 private bool FindSubstringElement (string s, string lower)\r
3091                 {\r
3092                         string stemp = lower;\r
3093                         int indexOf = stemp.IndexOf ("substring");\r
3094 \r
3095                         if (indexOf == -1)\r
3096                                 return false;\r
3097 \r
3098                         int oldIndex = -1;\r
3099                         while ((indexOf = stemp.IndexOf ("substring", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
3100                         {\r
3101 \r
3102                                 oldIndex = indexOf;\r
3103                                 bool failed = false;\r
3104 \r
3105                                 // Check is or part of column name\r
3106                                 if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
3107                                         continue;\r
3108 \r
3109                                 // is the element part of string element\r
3110                                 if (IsPartOfStringElement (stemp, indexOf))\r
3111                                         continue;\r
3112 \r
3113                                 return true;\r
3114                         }\r
3115                 \r
3116                         return false;                   \r
3117                 }\r
3118 \r
3119                 private bool FindInElement (string s, string lower, ref string s1, ref string s2)\r
3120                 {\r
3121                         string stemp = lower;\r
3122                         int indexOf = stemp.IndexOf ("in");\r
3123 \r
3124                         if (indexOf == -1)\r
3125                                 return false;\r
3126 \r
3127                         int oldIndex = -1;\r
3128                         while ((indexOf = stemp.IndexOf ("in", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
3129                         {\r
3130                                 oldIndex = indexOf;\r
3131                                 \r
3132                                 // check is the 'and' element part of string element\r
3133                                 if (IsPartOfStringElement (stemp, indexOf))\r
3134                                         continue;\r
3135 \r
3136 \r
3137                                 // Check is or part of something else for example column name\r
3138                                 if (indexOf != 0) \r
3139                                 {       \r
3140                                         if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
3141                                                 continue;\r
3142                                 }\r
3143                                 \r
3144                                 if (indexOf < stemp.Length + 2) \r
3145                                 {\r
3146                                         if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')\r
3147                                                 continue;\r
3148                                 }\r
3149 \r
3150                                 if (IsPartOfFunction (stemp, indexOf))\r
3151                                         continue;\r
3152 \r
3153                                 s1 = s.Substring (0, indexOf).Trim ();\r
3154                                 s2 = s.Substring (indexOf + 2).Trim ();\r
3155                                 return true;\r
3156                         }\r
3157                 \r
3158                         return false;                   \r
3159                 }\r
3160 \r
3161                 \r
3162                 #endregion // CheckElement methods\r
3163 \r
3164                 #region CreateElement methods\r
3165 \r
3166                 // \r
3167                 // These methods are going to be removed when way of parsing is changed\r
3168                 //\r
3169 \r
3170                 private void CreateOrElement (string s1, string s2, string inside) \r
3171                 {\r
3172                         CheckParenthesis (inside, ref s1, ref s2);\r
3173                         Elements.Add (new ExpressionOr (s1.Trim (), s2.Trim ()));\r
3174                 }\r
3175 \r
3176                 private void CreateAndElement (string s1, string s2, string inside)\r
3177                 {\r
3178                         CheckParenthesis (inside, ref s1, ref s2);\r
3179                         Elements.Add (new ExpressionAnd (s1.Trim (), s2.Trim ()));\r
3180                 }\r
3181 \r
3182                 private void CreateLikeElement (string s1, string s2, string inside)\r
3183                 {\r
3184                         CheckParenthesis (inside, ref s1, ref s2);\r
3185                         Elements.Add (new ExpressionLike (s1.Trim (), s2.Trim ()));\r
3186                 }\r
3187 \r
3188                 private void CreateInElement (string s1, string s2, string inside)\r
3189                 {\r
3190                         CheckParenthesis (inside, ref s1, ref s2);\r
3191                         Elements.Add (new ExpressionIn (s1.Trim (), s2.Trim ()));\r
3192                 }\r
3193 \r
3194                 private void CreateEqualsElement (string s1, string s2, string inside)\r
3195                 {\r
3196                         CheckParenthesis (inside, ref s1, ref s2);\r
3197                         Elements.Add (new ExpressionEquals (s1.Trim (), s2.Trim ()));                   \r
3198                 }\r
3199 \r
3200                 private void CreateUnequalsElement (string s1, string s2, string inside)\r
3201                 {\r
3202                         CheckParenthesis (inside, ref s1, ref s2);\r
3203                         Elements.Add (new ExpressionUnequals (s1.Trim (), s2.Trim ()));\r
3204                 }\r
3205 \r
3206                 private void CreateLessThanElement (string s1, string s2, string inside)\r
3207                 {\r
3208                         CheckParenthesis (inside, ref s1, ref s2);\r
3209                         Elements.Add (new ExpressionLessThan (s1.Trim (), s2.Trim ()));\r
3210                 }\r
3211 \r
3212                 private void CreateLessThanOrEqualElement (string s1, string s2, string inside)\r
3213                 {\r
3214                         CheckParenthesis (inside, ref s1, ref s2);\r
3215                         Elements.Add (new ExpressionLessThanOrEqual (s1.Trim (), s2.Trim ()));\r
3216                 }\r
3217 \r
3218                 private void CreateGreaterThanElement (string s1, string s2, string inside)\r
3219                 {\r
3220                         CheckParenthesis (inside, ref s1, ref s2);\r
3221                         Elements.Add (new ExpressionGreaterThan (s1.Trim (), s2.Trim ()));\r
3222                 }\r
3223 \r
3224 \r
3225                 private void CreateGreaterThanOrEqualElement (string s1, string s2, string inside)\r
3226                 {\r
3227                         CheckParenthesis (inside, ref s1, ref s2);\r
3228                         Elements.Add (new ExpressionGreaterThanOrEqual (s1.Trim (), s2.Trim ()));\r
3229                 }\r
3230 \r
3231                 private void CreateAdditionElement (string s1, string s2,  string inside)\r
3232                 {\r
3233                         CheckParenthesis (inside, ref s1, ref s2);                      \r
3234                         Elements.Add (new ExpressionAddition (s1.Trim (), s2.Trim ()));\r
3235                 }\r
3236 \r
3237                 private void CreateSubtractionElement (string s1, string s2,  string inside)\r
3238                 {\r
3239                         CheckParenthesis (inside, ref s1, ref s2);                      \r
3240                         Elements.Add (new ExpressionSubtraction (s1.Trim (), s2.Trim ()));\r
3241                 }\r
3242 \r
3243                 private void CreateMultiplyElement (string s1, string s2, string inside)\r
3244                 {\r
3245                         CheckParenthesis (inside, ref s1, ref s2);\r
3246                         Elements.Add (new ExpressionMultiply (s1.Trim (), s2.Trim ()));\r
3247                 }\r
3248 \r
3249                 private void CreateDivideElement (string s1, string s2, string inside)\r
3250                 {\r
3251                         CheckParenthesis (inside, ref s1, ref s2);\r
3252                         Elements.Add (new ExpressionDivide (s1.Trim (), s2.Trim ()));\r
3253                 }\r
3254 \r
3255                 private void CreateModulusElement (string s1, string s2, string inside)\r
3256                 {\r
3257                         CheckParenthesis (inside, ref s1, ref s2);\r
3258                         Elements.Add (new ExpressionModulus (s1.Trim (), s2.Trim ()));\r
3259                 }                       \r
3260 \r
3261                 #endregion // CreateElemnt methods\r
3262 \r
3263                 #region Little helppers\r
3264 \r
3265                 private void CheckParenthesis (string inside, ref string s1, ref string s2)\r
3266                 {\r
3267                         if (s1 == string.Empty && inside != string.Empty)\r
3268                                 s1 = inside;\r
3269                         else if (s2 == string.Empty && inside != string.Empty)\r
3270                                 s2 = inside;    \r
3271                 }\r
3272 \r
3273 \r
3274                 /// <summary>\r
3275                 ///  Checks is the element part of stringelement\r
3276                 /// </summary>\r
3277                 private bool IsPartOfStringElement (string s, int indexOf)\r
3278                 {\r
3279                         // count how many '-charachters are before or. If count is odd it means or IS between quotes\r
3280                         int quotes = 0;\r
3281                         for (int i = indexOf - 1; i >= 0; i--) \r
3282                         {\r
3283                                 if (s [i] == '\'')\r
3284                                         quotes++;\r
3285                         }\r
3286                         \r
3287                         if ((quotes & 1) != 0)\r
3288                                 return true;\r
3289                         else \r
3290                                 return false;\r
3291                 }\r
3292 \r
3293                 /// <summary>\r
3294                 ///  Checks is the element part of column table\r
3295                 /// </summary>\r
3296                 private bool IsPartOfColumnName (string s, int indexOf)\r
3297                 {\r
3298                         for (int i = indexOf; i >= 0; i--) \r
3299                         {\r
3300                                 \r
3301                                 // If the element is between [] it is part of columnname\r
3302                                 if (s [i] == '\'' || s [i] == ']') \r
3303                                 {\r
3304                                         break;\r
3305                                 }\r
3306                                 else if (s [i] == '[') \r
3307                                 {\r
3308                                         return true;\r
3309                                 }\r
3310                         }\r
3311 \r
3312                         return false;\r
3313                 }\r
3314 \r
3315 \r
3316                 /// <summary>\r
3317                 ///  Checks are element part of function\r
3318                 /// </summary>\r
3319                 private bool IsPartOfFunction (string s, int indexOf)\r
3320                 {\r
3321 \r
3322                         // \r
3323                         // If ',' or '\''  comes before '(' this element is not part of function's parameters\r
3324                         //\r
3325                         \r
3326                         for (int i = indexOf; i >= 0; i--) \r
3327                         {\r
3328                                 \r
3329                                 if (s [i] == '(' || s [i] == ',') \r
3330                                 {\r
3331                                         return true;\r
3332                                 }\r
3333                                 else if (s [i] == ')') \r
3334                                 {\r
3335                                         break;\r
3336                                 }\r
3337                         }\r
3338 \r
3339                         return false;\r
3340                 }\r
3341 \r
3342                 #endregion // Little helppers\r
3343 \r
3344                 #region ExpressionElementComparer\r
3345                 protected sealed class ExpressionElementComparer\r
3346                 {\r
3347                         object _value1 = null;\r
3348                         Type _t1 = null;\r
3349                         Type _RT1 = null;\r
3350                         DataRow _row = null;\r
3351 \r
3352                         public ExpressionElementComparer(ExpressionElement E1, DataRow Row)\r
3353                         {\r
3354                                 _value1 = E1.Result (Row);\r
3355 \r
3356                                 _row = Row;\r
3357 \r
3358                                 if (_value1 == null || _value1 == DBNull.Value)\r
3359                                         return;\r
3360 \r
3361                                 _t1 = _value1.GetType ();\r
3362                                 _RT1 = E1.ResultType (Row);\r
3363                         }\r
3364 \r
3365                         public int CompareTo (ExpressionElement E2)\r
3366                         {\r
3367                                 object value1 = _value1;\r
3368                                 object value2 = E2.Result (_row);\r
3369 \r
3370                                 if ((value1 == null || value1 == DBNull.Value) && (value2 == null || value2 == DBNull.Value))\r
3371                                         return 0;\r
3372                                 else if (value2 == null || value2 == DBNull.Value)\r
3373                                         return 1;\r
3374                                 else if (value1 == null || value1 == DBNull.Value)\r
3375                                         return -1;\r
3376 \r
3377                                 Type t2 = value2.GetType ();\r
3378                         \r
3379                                 Type RT2 = E2.ResultType (_row);\r
3380 \r
3381                                 if (_t1 == typeof (string) || t2 == typeof (string)) \r
3382                                 {\r
3383                                         // FIXME: If one of elements are string they both should be???\r
3384                                         return String.Compare(value1.ToString(), value2.ToString(), !_row.Table.CaseSensitive);\r
3385                                 }\r
3386 \r
3387                                 if (_t1 != t2) \r
3388                                 {\r
3389                                         value2 = Convert.ChangeType (value2, Type.GetTypeCode (_t1));\r
3390                                 }\r
3391 \r
3392                                 if (value1 is IComparable)\r
3393                                         return ((IComparable)value1).CompareTo(value2);\r
3394 \r
3395                                 return (int) _t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
3396                                         BindingFlags.InvokeMethod, null, \r
3397                                         value1, \r
3398                                         new object [] {value2});\r
3399                         }\r
3400                 }\r
3401                 #endregion\r
3402         }    \r
3403         #endif    \r
3404 }\r