2 // System.Data.ExpressionElement
\r
5 // Ville Palo <vi64pa@kolumbus.fi>
\r
7 // Copyright (C) Ville Palo, 2003
\r
9 // TODO: - Some functionelements and aggregates.
\r
10 // - New parsing style.
\r
16 using System.Reflection;
\r
18 using System.Collections;
\r
21 namespace System.Data
\r
25 /// The main element which includes whole expression
\r
27 internal class ExpressionMainElement : ExpressionElement
\r
32 public ExpressionMainElement (string s)
\r
34 s = ExpressionElement.ValidateExpression (s);
\r
35 ParseExpression (s);
\r
38 public override bool Test (DataRow Row)
\r
41 foreach (ExpressionElement El in Elements)
\r
54 // O_P_E_R_A_T_O_R_S
\r
60 internal class ExpressionEquals : ExpressionElement
\r
63 public ExpressionEquals (string exp1, string exp2)
\r
67 ParseExpression (exp1);
\r
68 ParseExpression (exp2);
\r
71 public override bool Test (DataRow Row)
\r
74 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
75 ExpressionElement E2 = (ExpressionElement)Elements [1];
\r
77 return ExpressionElement.Compare (E1, E2, Row) == 0;
\r
84 internal class ExpressionLessThan : ExpressionElement
\r
87 public ExpressionLessThan (string exp1, string exp2)
\r
91 ParseExpression (exp1);
\r
92 ParseExpression (exp2);
\r
95 public override bool Test (DataRow Row)
\r
98 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
99 ExpressionElement E2 = (ExpressionElement)Elements [1];
\r
101 return ExpressionElement.Compare (E1, E2, Row) < 0;
\r
108 internal class ExpressionLessThanOrEqual : ExpressionElement
\r
111 public ExpressionLessThanOrEqual (string exp1, string exp2)
\r
115 ParseExpression (exp1);
\r
116 ParseExpression (exp2);
\r
119 public override bool Test (DataRow Row)
\r
122 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
123 ExpressionElement E2 = (ExpressionElement)Elements [1];
\r
125 return ExpressionElement.Compare (E1, E2, Row) <= 0;
\r
132 internal class ExpressionGreaterThan : ExpressionElement
\r
135 public ExpressionGreaterThan (string exp1, string exp2)
\r
139 ParseExpression (exp1);
\r
140 ParseExpression (exp2);
\r
143 public override bool Test (DataRow Row)
\r
146 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
147 ExpressionElement E2 = (ExpressionElement)Elements [1];
\r
149 return ExpressionElement.Compare (E1, E2, Row) > 0;
\r
156 internal class ExpressionGreaterThanOrEqual : ExpressionElement
\r
159 public ExpressionGreaterThanOrEqual (string exp1, string exp2)
\r
163 ParseExpression (exp1);
\r
164 ParseExpression (exp2);
\r
167 public override bool Test (DataRow Row)
\r
170 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
171 ExpressionElement E2 = (ExpressionElement)Elements [1];
\r
173 return ExpressionElement.Compare (E1, E2, Row) >= 0;
\r
180 internal class ExpressionUnequals : ExpressionElement
\r
183 public ExpressionUnequals (string exp1, string exp2)
\r
187 ParseExpression (exp1);
\r
188 ParseExpression (exp2);
\r
191 public override bool Test (DataRow Row)
\r
194 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
195 ExpressionElement E2 = (ExpressionElement)Elements [1];
\r
197 return ExpressionElement.Compare (E1, E2, Row) != 0;
\r
203 /// Class for LIKE-operator
\r
205 internal class ExpressionLike : ExpressionElement
\r
208 public ExpressionLike (string exp1, string exp2)
\r
210 ParseExpression (exp1);
\r
211 ParseExpression (exp2);
\r
214 public override bool Test (DataRow Row)
\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
222 if (value1.GetType () != typeof (string) || value2.GetType () != typeof (string))
\r
223 throw new Exception (); // TODO: what exception
\r
225 string operand1 = value1.ToString ();
\r
226 string operand2 = value2.ToString ();
\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
237 indexOf = operand2.IndexOf ("*");
\r
238 while (indexOf != -1)
\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
246 operand2 = operand2.Remove (indexOf + 1, 1);
\r
247 operand2 = operand2.Remove (indexOf -1, 1);
\r
251 indexOf = operand2.IndexOf ("*", oldIndex);
\r
255 indexOf = operand2.IndexOf ("%");
\r
256 while (indexOf != -1)
\r
259 oldIndex = indexOf + 1;
\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
265 operand2 = operand2.Remove (indexOf + 1, 1);
\r
266 operand2 = operand2.Remove (indexOf -1, 1);
\r
270 indexOf = operand2.IndexOf ("%", oldIndex);
\r
273 int len2 = operand2.Length;
\r
274 int startIndex = 0;
\r
275 while ((startIndex + len2) <= operand1.Length)
\r
277 if (String.Compare (operand1.Substring (startIndex, len2), operand2, !Row.Table.CaseSensitive) == 0)
\r
290 internal class ExpressionOr : ExpressionElement
\r
292 public ExpressionOr (string exp1, string exp2)
\r
294 ParseExpression (exp1);
\r
295 ParseExpression (exp2);
\r
298 public override bool Test (DataRow Row)
\r
300 foreach (ExpressionElement El in Elements)
\r
313 internal class ExpressionAnd : ExpressionElement
\r
315 public ExpressionAnd (string exp1, string exp2)
\r
317 ParseExpression (exp1);
\r
318 ParseExpression (exp2);
\r
321 public override object Result (DataRow Row)
\r
327 public override bool Test (DataRow Row)
\r
329 foreach (ExpressionElement El in Elements)
\r
331 if (!El.Test (Row))
\r
341 // A_R_I_T_H_M_E_T_I_C O_P_E_R_A_T_O_R_S
\r
347 internal class ExpressionAddition : ExpressionElement
\r
349 public ExpressionAddition (string exp1, string exp2)
\r
353 ParseExpression (exp1);
\r
354 ParseExpression (exp2);
\r
357 public override Type ResultType (DataRow Row)
\r
359 Type ResultType = typeof (string);
\r
360 ExpressionElement exp1Temp = ((ExpressionElement)Elements [0]);
\r
361 ExpressionElement exp2Temp = ((ExpressionElement)Elements [1]);
\r
363 if (exp1Temp.ResultType (Row) == typeof (string) || exp2Temp.ResultType (Row) == typeof (string))
\r
364 ResultType = typeof (string);
\r
366 else if (exp1Temp.ResultType (Row) == typeof (long) || exp2Temp.ResultType (Row) == typeof (long))
\r
367 ResultType = typeof (long);
\r
369 else if (exp1Temp.ResultType (Row) == typeof (int) || exp2Temp.ResultType (Row) == typeof (int))
\r
370 ResultType = typeof (int);
\r
375 public override object Result (DataRow Row)
\r
377 return CalculateResult (Row);
\r
380 protected override object Calculate (object value1, object value2, Type TempType)
\r
382 object Result = null;
\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
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
412 //else if (TempType == typeof (DateTime))
\r
413 // Result = (DateTime)value1 + (DateTime)value2;
\r
419 // This method is shouldnt never invoked
\r
420 public override bool Test (DataRow Row)
\r
422 throw new EvaluateException ();
\r
429 internal class ExpressionSubtraction : ExpressionElement
\r
431 public ExpressionSubtraction (string exp1, string exp2)
\r
435 ParseExpression (exp1);
\r
436 ParseExpression (exp2);
\r
439 public override object Result (DataRow Row)
\r
441 return CalculateResult (Row);
\r
444 // This method is shouldnt never invoked
\r
445 public override bool Test (DataRow Row)
\r
447 throw new EvaluateException ();
\r
450 protected override object Calculate (object value1, object value2, Type TempType)
\r
452 object Result = null;
\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
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
483 //else if (TempType == typeof (DateTime))
\r
484 // Result = (DateTime)value1 - (DateTime)value2;
\r
493 internal class ExpressionMultiply : ExpressionElement
\r
495 public ExpressionMultiply (string exp1, string exp2)
\r
499 ParseExpression (exp1);
\r
500 ParseExpression (exp2);
\r
503 public override Type ResultType (DataRow Row)
\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
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
515 else if (t1 == typeof (long) || t2 == typeof (long))
\r
516 ResultType = typeof (long);
\r
518 else if (t1 == typeof (int) || t2 == typeof (int))
\r
519 ResultType = typeof (int);
\r
524 public override object Result (DataRow Row)
\r
526 return CalculateResult (Row);
\r
529 public override bool Test (DataRow Row)
\r
531 throw new EvaluateException ();
\r
534 protected override object Calculate (object value1, object value2, Type TempType)
\r
536 object Result = null;
\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
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
564 //else if (TempType == typeof (DateTime))
\r
565 // Result = (DateTime)value1 * (DateTime)value2;
\r
575 internal class ExpressionDivide : ExpressionElement
\r
577 public ExpressionDivide (string exp1, string exp2)
\r
581 ParseExpression (exp1);
\r
582 ParseExpression (exp2);
\r
585 public override object Result (DataRow Row)
\r
587 return CalculateResult (Row);
\r
590 // This method is shouldnt never invoked
\r
591 public override bool Test (DataRow Row)
\r
593 throw new EvaluateException ();
\r
596 protected override object Calculate (object value1, object value2, Type TempType)
\r
598 object Result = null;
\r
600 if (TempType == typeof (long))
\r
601 Result = (long)value1 / (long)value2;
\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
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
629 //else if (TempType == typeof (DateTime))
\r
630 // Result = (DateTime)value1 / (DateTime)value2;
\r
639 internal class ExpressionModulus : ExpressionElement
\r
641 public ExpressionModulus (string exp1, string exp2)
\r
645 ParseExpression (exp1);
\r
646 ParseExpression (exp2);
\r
649 public override object Result (DataRow Row)
\r
651 return CalculateResult (Row);
\r
654 // This method is shouldnt never invoked
\r
655 public override bool Test (DataRow Row)
\r
657 throw new EvaluateException ();
\r
660 protected override object Calculate (object value1, object value2, Type TempType)
\r
662 object Result = null;
\r
664 if (TempType == typeof (long))
\r
665 Result = (long)value1 % (long)value2;
\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
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
693 //else if (TempType == typeof (DateTime))
\r
694 // Result = (DateTime)value1 / (DateTime)value2;
\r
701 // _____A_G_G_R_E_G_A_T_E_S_____
\r
704 internal class ExpressionAggregate : ExpressionElement
\r
707 public ExpressionAggregate()
\r
711 public ExpressionAggregate(string s)
\r
713 s = ExpressionElement.ValidateExpression (s);
\r
714 ParseExpression (s);
\r
718 public override bool Test (DataRow Row)
\r
720 throw new EvaluateException ();
\r
723 public override object Result(DataRow Row)
\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
730 public virtual object Result(DataRow[] rows)
\r
732 return ((ExpressionAggregate)Elements[0]).Result(rows);
\r
736 protected virtual void ParseParameters (string s)
\r
738 string stemp = s.ToLower ();
\r
739 bool inString = false;
\r
743 while (!s.StartsWith ("("))
\r
744 s = s.Remove (0, 1);
\r
747 s = s.Remove (0, 1);
\r
749 int parentheses = 0;
\r
750 for (int i = 0; i < s.Length; i++)
\r
754 inString = !inString;
\r
755 else if (s [i] == '(')
\r
757 else if (s [i] == ')')
\r
760 if ((s [i] == ',' || s [i] == ')') && !inString && parentheses == -1)
\r
761 { // Parameter changed
\r
765 p1 = s.Substring (0, i);
\r
772 throw new Exception ();
\r
774 ParseExpression (p1);
\r
780 /// Class for Sum (column_Name)
\r
782 internal class ExpressionSum : ExpressionAggregate
\r
784 public ExpressionSum (string exp1)
\r
786 ParseParameters (exp1);
\r
789 public override object Result(DataRow[] rows)
\r
791 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
792 object value1 = E1.Result (rows[0]);
\r
793 Type t1 = value1.GetType ();
\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
799 if (E1 is ExpressionSingleElement)
\r
802 // This should be optimized somehow
\r
803 for (int i = 0; i < rows.Length; i++)
\r
806 // TODO: other types and exceptions
\r
807 object v = E1.Result (rows[i]);
\r
810 if (v == null || v == DBNull.Value)
\r
813 if (t1 == typeof (long))
\r
815 result = (long)result + (long)v;
\r
817 else if (t1 == typeof (int))
\r
819 result = (int)result + (int)v;
\r
821 else if (t1 == typeof (short))
\r
823 result = (short)result + (short)v;
\r
825 else if (t1 == typeof (double))
\r
827 result = (double)result + (double)v;
\r
829 else if (t1 == typeof (float))
\r
831 result = (float)result + (float)v;
\r
834 throw new NotImplementedException ();
\r
843 // Copy: This method is copy-paste in every Aggregate class.
\r
848 /// Class for Avg (column_Name)
\r
850 internal class ExpressionAvg : ExpressionAggregate
\r
852 public ExpressionAvg (string exp1)
\r
854 ParseParameters (exp1);
\r
857 public override object Result(DataRow[] rows)
\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
864 if (E1 is ExpressionSingleElement)
\r
868 // This should be optimized somehow
\r
869 for (int i = 0; i < rows.Length; i++)
\r
872 // TODO: other types and exceptions
\r
873 object v = E1.Result (rows[i]);
\r
875 if (v == null || v == DBNull.Value)
\r
880 if (result == null)
\r
883 if (t1 == typeof (long))
\r
885 result = (long)result + (long)v;
\r
887 else if (t1 == typeof (int))
\r
889 result = (int)result + (int)v;
\r
891 else if (t1 == typeof (short))
\r
893 result = (short)result + (short)v;
\r
895 else if (t1 == typeof (double))
\r
897 result = (double)result + (double)v;
\r
899 else if (t1 == typeof (float))
\r
901 result = (float)result + (float)v;
\r
904 throw new NotImplementedException ();
\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
923 /// This is used from ExpressionStdDev for evaluating avg.
\r
925 public ExpressionAvg (ExpressionElement E)
\r
933 /// Class for Min (column_Name)
\r
935 internal class ExpressionMin : ExpressionAggregate
\r
937 public ExpressionMin (string exp1)
\r
939 ParseParameters (exp1);
\r
942 public override object Result(DataRow[] rows)
\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
949 if (E1 is ExpressionSingleElement)
\r
953 // This should be optimized somehow
\r
954 for (int i = 0; i < rows.Length; i++)
\r
957 // TODO: other types and exceptions
\r
958 object v = E1.Result (rows[i]);
\r
960 if (v == null || v == DBNull.Value)
\r
965 if (result == null)
\r
968 object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default |
\r
969 BindingFlags.InvokeMethod, null,
\r
971 new object [] {result});
\r
973 if ((int)CompResult < 0)
\r
986 /// Class for Max (column_Name)
\r
988 internal class ExpressionMax : ExpressionAggregate
\r
990 public ExpressionMax (string exp1)
\r
992 ParseParameters (exp1);
\r
995 public override object Result(DataRow[] rows)
\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
1002 if (E1 is ExpressionSingleElement)
\r
1006 // This should be optimized somehow
\r
1007 for (int i = 0; i < rows.Length; i++)
\r
1010 // TODO: other types and exceptions
\r
1011 object v = E1.Result (rows[i]);
\r
1013 if (v == null || v == DBNull.Value)
\r
1016 t1 = v.GetType ();
\r
1018 if (result == null)
\r
1021 object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default |
\r
1022 BindingFlags.InvokeMethod, null,
\r
1024 new object [] {result});
\r
1026 if ((int)CompResult > 0)
\r
1040 /// Class for count (column)
\r
1042 internal class ExpressionCount : ExpressionAggregate
\r
1044 public ExpressionCount (string exp1)
\r
1046 ParseParameters (exp1);
\r
1049 public override object Result(DataRow[] rows)
\r
1051 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
1054 if (E1 is ExpressionSingleElement)
\r
1055 count = rows.Length;
\r
1060 public override object Result (DataRow Row)
\r
1062 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
1065 if (E1 is ExpressionSingleElement)
\r
1068 count = Row.Table.Rows.Count;
\r
1077 /// Class for StdDev (column)
\r
1079 internal class ExpressionStdev : ExpressionAggregate
\r
1081 public ExpressionStdev (string exp1)
\r
1083 ParseParameters (exp1);
\r
1086 public override object Result(DataRow[] rows)
\r
1088 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
1089 ExpressionAvg Avg = new ExpressionAvg (E1);
\r
1091 object tempAvg = Avg.Result (rows[0]);
\r
1094 double result = 0;
\r
1096 if (tempAvg.GetType () == typeof (int))
\r
1097 avg = (double)(int)tempAvg;
\r
1099 if (E1 is ExpressionSingleElement)
\r
1102 for (int i = 0; i <rows.Length; i++)
\r
1104 // (value - avg)²
\r
1105 object v = E1.Result (rows[i]);
\r
1107 if (v == null || v == DBNull.Value)
\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
1117 throw new NotImplementedException ();
\r
1119 result += Math.Pow (sum, 2);
\r
1122 result = result / (rows.Length - 1);
\r
1123 result = Math.Sqrt (result);
\r
1133 /// Class for Var (column)
\r
1135 internal class ExpressionVar : ExpressionAggregate
\r
1137 public ExpressionVar (string exp1)
\r
1139 ParseParameters (exp1);
\r
1142 public override object Result(DataRow[] rows)
\r
1144 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
1145 ExpressionAvg Avg = new ExpressionAvg (E1);
\r
1147 object tempAvg = Avg.Result (rows[0]);
\r
1150 double result = 0;
\r
1152 if (tempAvg.GetType () == typeof (int))
\r
1153 avg = (double)(int)tempAvg;
\r
1155 if (E1 is ExpressionSingleElement)
\r
1158 for (int i = 0; i < rows.Length; i++)
\r
1162 // (value - avg)²
\r
1163 object v = E1.Result (rows[i]);
\r
1165 if (v == null || v == DBNull.Value)
\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
1175 throw new NotImplementedException ();
\r
1177 result += Math.Pow (sum, 2);
\r
1180 result = result / (rows.Length - 1);
\r
1190 // _____F_U_ N_C_T_I_O_N_S_______
\r
1194 /// Class for len (string) function
\r
1196 internal class ExpressionLen : ExpressionElement
\r
1198 public ExpressionLen (string exp1)
\r
1200 _ResultType = typeof (int);
\r
1201 ParseParameters (exp1);
\r
1204 public override object Result (DataRow Row)
\r
1206 ExpressionElement E1 = ((ExpressionElement)Elements [0]);
\r
1207 object value1 = E1.Result (Row);
\r
1209 return value1.ToString ().Length;
\r
1212 public override bool Test (DataRow Row)
\r
1214 throw new EvaluateException ();
\r
1217 public void ParseParameters (string s)
\r
1219 string stemp = s.ToLower ();
\r
1220 bool inString = false;
\r
1224 while (!s.StartsWith ("("))
\r
1225 s = s.Remove (0, 1);
\r
1228 s = s.Remove (0, 1);
\r
1229 int parentheses = 0;
\r
1230 for (int i = 0; i < s.Length; i++)
\r
1233 if (s [i] == '\'')
\r
1234 inString = !inString;
\r
1235 else if (s [i] == '(')
\r
1237 else if (s [i] == ')')
\r
1240 if ((s [i] == ',' || s [i] == ')') && !inString && parentheses == -1)
\r
1241 { // Parameter changed
\r
1245 p1 = s.Substring (0, i);
\r
1252 throw new Exception ();
\r
1254 ParseExpression (p1);
\r
1259 /// Class for iif (exp1, truepart, falsepart) function
\r
1261 internal class ExpressionIif : ExpressionElement
\r
1263 public ExpressionIif (string exp)
\r
1265 ParseParameters (exp);
\r
1268 public override object Result (DataRow Row)
\r
1270 ExpressionElement E1 = ((ExpressionElement)Elements [0]);
\r
1271 ExpressionElement E2 = ((ExpressionElement)Elements [1]);
\r
1272 ExpressionElement E3 = ((ExpressionElement)Elements [2]);
\r
1274 if (E1.Test (Row)) // expression
\r
1275 return E2.Result (Row); // truepart
\r
1277 return E3.Result (Row); // false part
\r
1280 // This method is shouldnt never invoked
\r
1281 public override bool Test (DataRow Row)
\r
1283 throw new EvaluateException ();
\r
1286 public override Type ResultType (DataRow Row)
\r
1288 ExpressionElement E1 = ((ExpressionElement)Elements [0]);
\r
1289 ExpressionElement E2 = ((ExpressionElement)Elements [1]);
\r
1290 ExpressionElement E3 = ((ExpressionElement)Elements [2]);
\r
1292 if (E1.Test (Row)) // expression
\r
1293 return E2.Result (Row).GetType (); // truepart
\r
1295 return E3.Result (Row).GetType (); // false part
\r
1299 /// Parses expressions in parameters (exp, truepart, falsepart)
\r
1301 private void ParseParameters (string s)
\r
1303 bool inString = false;
\r
1304 string stemp = s.ToLower ();
\r
1308 s = s.Substring (stemp.IndexOf ("iif") + 3);
\r
1311 while (!s.StartsWith ("("))
\r
1312 s = s.Remove (0, 1);
\r
1315 s = s.Remove (0, 1);
\r
1316 int parentheses = 0;
\r
1317 for (int i = 0; i < s.Length; i++)
\r
1320 if (s [i] == '\'')
\r
1321 inString = !inString;
\r
1322 else if (s [i] == '(')
\r
1324 else if (s [i] == ')')
\r
1327 if ((s [i] == ',' && !inString && parentheses == 0) ||
\r
1328 (s [i] == ')' && i == (s.Length -1)))
\r
1329 { // Parameter changed
\r
1333 p1 = s.Substring (0, i);
\r
1334 s = s.Substring (i + 1);
\r
1338 else if (p2 == null)
\r
1340 p2 = s.Substring (0, i);
\r
1341 s = s.Substring (i + 1);
\r
1345 else if (p3 == null)
\r
1347 p3 = s.Substring (0, i);
\r
1348 s = s.Substring (i + 1);
\r
1353 throw new Exception (); // FIXME: What exception
\r
1357 if (p1 == null || p2 == null || p3 == null)
\r
1358 throw new Exception ();
\r
1360 ParseExpression (p1);
\r
1361 ParseExpression (p2);
\r
1362 ParseExpression (p3);
\r
1367 /// Class for isnull (expression, returnvalue) function
\r
1369 internal class ExpressionIsNull : ExpressionElement
\r
1371 public ExpressionIsNull (string exp)
\r
1373 ParseParameters (exp);
\r
1376 public override object Result (DataRow Row)
\r
1378 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
1379 ExpressionElement E2 = (ExpressionElement)Elements [1];
\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
1389 public override Type ResultType (DataRow Row)
\r
1391 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
1392 ExpressionElement E2 = (ExpressionElement)Elements [1];
\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
1399 return R1.GetType ();
\r
1403 /// IsNull function does not return boolean value, so throw exception
\r
1405 public override bool Test (DataRow Row)
\r
1407 throw new EvaluateException ();
\r
1411 /// Parses parameters of function and invoke ParseExpression methods
\r
1413 private void ParseParameters (string s)
\r
1415 bool inString = false;
\r
1416 string stemp = s.ToLower ();
\r
1420 s = s.Substring (stemp.IndexOf ("isnull") + 6);
\r
1423 while (!s.StartsWith ("("))
\r
1424 s = s.Remove (0, 1);
\r
1427 s = s.Remove (0, 1);
\r
1428 int parentheses = 0;
\r
1429 for (int i = 0; i < s.Length; i++)
\r
1432 if (s [i] == '\'')
\r
1433 inString = !inString;
\r
1434 else if (s [i] == '(')
\r
1436 else if (s [i] == ')')
\r
1439 if ((s [i] == ',' && !inString && parentheses == 0) ||
\r
1440 (s [i] == ')' && i == (s.Length -1)))
\r
1441 { // Parameter changed
\r
1445 p1 = s.Substring (0, i);
\r
1446 s = s.Substring (i + 1);
\r
1450 else if (p2 == null)
\r
1452 p2 = s.Substring (0, i);
\r
1453 s = s.Substring (i + 1);
\r
1458 throw new Exception (); // FIXME: What exception
\r
1462 if (p1 == null || p2 == null)
\r
1463 throw new Exception ();
\r
1465 ParseExpression (p1);
\r
1466 ParseExpression (p2);
\r
1471 /// Class for Substring (expression, start, length) function
\r
1473 internal class ExpressionSubstring : ExpressionElement
\r
1475 public ExpressionSubstring (string exp)
\r
1477 ParseParameters (exp);
\r
1478 _ResultType = typeof (string);
\r
1481 public override object Result (DataRow Row)
\r
1483 ExpressionElement E1 = (ExpressionElement)Elements [0];
\r
1484 ExpressionElement E2 = (ExpressionElement)Elements [1];
\r
1485 ExpressionElement E3 = (ExpressionElement)Elements [2];
\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
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
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
1505 string str = value1.ToString ();
\r
1506 int start = (int)value2;
\r
1507 int length = (int)value3;
\r
1509 if (str.Length < start)
\r
1510 str = string.Empty;
\r
1513 if ((start + length - 1) > str.Length)
\r
1514 str = str.Substring (start - 1);
\r
1516 str = str.Substring (start - 1, length);
\r
1523 /// IsNull function does not return boolean value, so throw exception
\r
1525 public override bool Test (DataRow Row)
\r
1527 throw new EvaluateException ();
\r
1531 /// Parses parameters of function and invoke ParseExpression methods
\r
1533 private void ParseParameters (string s)
\r
1535 bool inString = false;
\r
1536 string stemp = s.ToLower ();
\r
1541 s = s.Substring (stemp.IndexOf ("substring") + 9);
\r
1544 while (!s.StartsWith ("("))
\r
1545 s = s.Remove (0, 1);
\r
1548 s = s.Remove (0, 1);
\r
1549 int parentheses = 0;
\r
1550 for (int i = 0; i < s.Length; i++)
\r
1553 if (s [i] == '\'')
\r
1554 inString = !inString;
\r
1555 else if (s [i] == '(')
\r
1557 else if (s [i] == ')')
\r
1561 if ((s [i] == ',' && !inString && parentheses == 0) ||
\r
1562 (s [i] == ')' && i == (s.Length -1)))
\r
1563 { // Parameter changed
\r
1567 p1 = s.Substring (0, i);
\r
1568 s = s.Substring (i + 1);
\r
1572 else if (p2 == null)
\r
1574 p2 = s.Substring (0, i);
\r
1575 s = s.Substring (i + 1);
\r
1579 else if (p3 == null)
\r
1581 p3 = s.Substring (0, i);
\r
1582 s = s.Substring (i + 1);
\r
1587 throw new Exception (); // FIXME: What exception
\r
1591 if (p1 == null || p2 == null)
\r
1592 throw new Exception ();
\r
1594 ParseExpression (p1);
\r
1595 ParseExpression (p2);
\r
1596 ParseExpression (p3);
\r
1601 /// Class for In (exp, exp, exp, ...) function
\r
1603 internal class ExpressionIn : ExpressionElement
\r
1605 public ExpressionIn (string exp1, string exp2)
\r
1607 ParseExpression(exp1);
\r
1608 ParseParameters (exp2);
\r
1612 /// IsNull function does not return boolean value, so throw exception
\r
1614 public override bool Test (DataRow Row)
\r
1616 ExpressionElement E;
\r
1617 ExpressionElement columnElement = (ExpressionElement)Elements [0];
\r
1619 ExpressionElementComparer comparer = new ExpressionElementComparer(columnElement, Row);
\r
1621 for (int i = 1; i < Elements.Count; i++)
\r
1623 E = (ExpressionElement)Elements [i];
\r
1624 if(comparer.CompareTo(E) == 0)
\r
1631 /// Parses parameters of function and invoke ParseExpression methods
\r
1633 private void ParseParameters (string s)
\r
1635 bool inString = false;
\r
1636 ArrayList parameters = new ArrayList();
\r
1639 while (!s.StartsWith ("("))
\r
1640 s = s.Remove (0, 1);
\r
1643 s = s.Remove (0, 1);
\r
1644 int parentheses = 0;
\r
1645 for (int i = 0; i < s.Length; i++)
\r
1648 if (s [i] == '\'')
\r
1649 inString = !inString;
\r
1650 else if (s [i] == '(')
\r
1652 else if (s [i] == ')')
\r
1656 if ((s [i] == ',' && !inString && parentheses == 0) ||
\r
1657 (s [i] == ')' && i == (s.Length -1)))
\r
1659 parameters.Add(s.Substring (0, i));
\r
1660 s = s.Substring (i + 1);
\r
1665 for (int i = 0; i < parameters.Count; i++)
\r
1666 ParseExpression((string)parameters[i]);
\r
1671 /// Class for just one element for example string, int, ...
\r
1673 internal class ExpressionSingleElement : ExpressionElement
\r
1675 private object Element = null;
\r
1677 public ExpressionSingleElement (string s)
\r
1679 // TODO: Every type should be checked
\r
1680 if (s.StartsWith ("'") && s.EndsWith ("'"))
\r
1682 Element = s.Substring (1, s.Length - 2);
\r
1683 _ResultType = typeof (string);
\r
1685 else if (!Char.IsDigit (s [0]) && s [0] != '-' && s [0] != '+')
\r
1688 _ResultType = typeof (DataColumn);
\r
1690 else if (s.StartsWith ("#") && s.EndsWith ("#"))
\r
1692 Element = DateTime.Parse (s.Substring (1, s.Length - 2));
\r
1693 _ResultType = typeof (DateTime);
\r
1699 Element = int.Parse (s);
\r
1700 _ResultType = typeof (int);
\r
1704 Element = Decimal.Parse (s);
\r
1705 _ResultType = typeof (Decimal);
\r
1710 public override object Result (DataRow Row)
\r
1712 object Result = null;
\r
1713 if (ResultType (Row) == typeof (DataColumn))
\r
1716 if (!Row.Table.Columns.Contains (Element.ToString ()))
\r
1717 throw new EvaluateException ("Column name '" + Element.ToString () + "' not found.");
\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
1733 public override bool Test (DataRow Row)
\r
1735 throw new EvaluateException ();
\r
1740 /// Parent class of all the elements of expression
\r
1742 internal abstract class ExpressionElement
\r
1744 enum OP {OPERATOR, OPERAND};
\r
1745 enum OPERATOR_TYPE {SYMBOLIC, LITERAL, UNDEFINED};
\r
1746 enum OPERAND_TYPE {NUMERIC, STRING, UNDEFINED};
\r
1749 // TODO/FIXME: This class should be inherited more than once. I mean own subclass for operators, functions,...
\r
1752 protected string exp1;
\r
1753 protected string exp2;
\r
1754 protected Type _ResultType;
\r
1756 protected ArrayList Elements = new ArrayList ();
\r
1758 enum AGGREGATE {SUM, AVG, MIN, MAX, COUNT, STDEV, VAR}
\r
1759 //protected ArrayList Singles = new ArrayList ();
\r
1762 /// Tells does the current expressions match to current DataRow
\r
1764 abstract public bool Test (DataRow Row);
\r
1766 public virtual object Result (DataRow Row) {return null;}
\r
1768 public virtual Type ResultType (DataRow Row)
\r
1770 return _ResultType;
\r
1773 protected object CalculateResult (DataRow Row)
\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
1784 if (value1 == DBNull.Value && value2 == DBNull.Value)
\r
1787 // TODO: More types
\r
1789 if (t1 == typeof (string) || t2 == typeof (string))
\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
1799 value2 = Convert.ChangeType (value2, Type.GetTypeCode (t1));
\r
1801 Result = Calculate (value1, value2, t1);
\r
1805 protected virtual object Calculate (object value1, object value2, Type TempType)
\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
1814 protected static int Compare (ExpressionElement E1, ExpressionElement E2, DataRow Row)
\r
1816 ExpressionElementComparer comparer = new ExpressionElementComparer(E1, Row);
\r
1818 return comparer.CompareTo(E2);
\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
1825 internal static string ValidateExpression (string s)
\r
1828 // TODO: find out nice way to do this. This is NOT nice way :-P
\r
1830 //string temp = "";
\r
1831 OP op = OP.OPERAND;
\r
1832 OPERATOR_TYPE operatorType = OPERATOR_TYPE.UNDEFINED;
\r
1834 StringBuilder strOperator = new StringBuilder();
\r
1835 StringBuilder strOperand = new StringBuilder();
\r
1837 int parentheses = 0;
\r
1838 StringBuilder newExp = new StringBuilder();
\r
1839 bool isDigit = false;
\r
1840 //bool litOperator = false;
\r
1843 for (int i = 0; i < s.Length; i++)
\r
1851 if ((c == '\n' || c == '\t') && quotes == 0)
\r
1854 if (op == OP.OPERAND && c == '(')
\r
1856 else if (op == OP.OPERAND && c == ')')
\r
1859 if (c == ' ' && op == OP.OPERAND && (quotes % 2) == 0 && parentheses == 0)
\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
1870 if (op == OP.OPERAND)
\r
1873 if (!Char.IsDigit (c) && isDigit && (quotes % 2) == 0)
\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
1880 operatorType = OPERATOR_TYPE.UNDEFINED;
\r
1883 strOperand.Append(c);
\r
1886 if (op == OP.OPERATOR)
\r
1890 if (operatorType == OPERATOR_TYPE.UNDEFINED)
\r
1893 if (c == '<' || c == '=' || c == '>' || c == '*' || c == '/' || c == '%'
\r
1894 || c == '-' || c == '+')
\r
1896 operatorType = OPERATOR_TYPE.SYMBOLIC;
\r
1897 else if (c != ' ')
\r
1898 operatorType = OPERATOR_TYPE.LITERAL;
\r
1900 else if (operatorType == OPERATOR_TYPE.SYMBOLIC)
\r
1903 //Checking for operators following one another
\r
1904 if ((c == '=' || c== '<' || c== '>') &&
\r
1905 (strOperator.Length == 2) &&
\r
1906 (strOperator[0] == ' '))
\r
1908 char chSecond = strOperator[1];
\r
1909 if (chSecond == '+' ||
\r
1910 chSecond == '-' ||
\r
1911 chSecond == '%' ||
\r
1913 throw new SyntaxErrorException (
\r
1914 "The operator " + strOperator.ToString() + c + " is not valid");
\r
1917 // this is COPY-PASTE
\r
1919 if (newExp[newExp.Length - 1] != ' ' &&
\r
1920 strOperator[0] != ' ')
\r
1921 newExp.Append(' ');
\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
1928 if (Char.IsDigit (c))
\r
1931 strOperand.Remove(0, strOperand.Length);
\r
1932 strOperand.Append(c);
\r
1938 if (operatorType == OPERATOR_TYPE.LITERAL && c == ' ')
\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
1946 strOperand.Append(' ');
\r
1950 if (Char.IsDigit (c) && operatorType != OPERATOR_TYPE.LITERAL)
\r
1954 if (newExp[newExp.Length - 1] != ' ' &&
\r
1955 strOperator[0] != ' ')
\r
1956 newExp.Append(' ');
\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
1963 if (Char.IsDigit (c))
\r
1966 strOperand.Remove(0, strOperand.Length);
\r
1967 strOperand.Append(c);
\r
1970 else if (c != ' ')
\r
1971 strOperator.Append(c);
\r
1975 if (op == OP.OPERATOR)
\r
1976 throw new SyntaxErrorException (
\r
1977 "Missing operand after '" + strOperator.ToString() + "' operator");
\r
1980 int max = strOperand.Length;
\r
1981 for (int it = 0; it < max; it++)
\r
1982 newExp.Append(strOperand[it]);
\r
1985 return newExp.ToString();
\r
1989 /// Finds and creates Expression elements.
\r
1990 /// This presumes that expression is valid.
\r
1992 protected void ParseExpression (string s)
\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
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
2005 int startIndex = lower.IndexOf ('(');
\r
2007 // Find parenthesis
\r
2008 if (startIndex != -1)
\r
2010 string functionName = String.Empty;
\r
2011 if (startIndex > 0)
\r
2013 int functionStart = lower.LastIndexOf('=', startIndex-1, startIndex);
\r
2014 if (functionStart < 0)
\r
2016 functionName = lower.Substring(functionStart, startIndex);
\r
2018 functionName = functionName.Trim ();
\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
2032 int i = startIndex + 1;
\r
2033 int max = lower.Length;
\r
2035 for (int par = 1; par > 0 && i < max; i++)
\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
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
2058 else if (FindAndElement (s, lower, ref string1, ref string2))
\r
2059 CreateAndElement (string1, string2, inside);
\r
2062 else if (FindLikeElement (s, lower, ref string1, ref string2))
\r
2063 CreateLikeElement (string1, string2, inside);
\r
2066 else if (FindInElement (s, lower, ref string1, ref string2))
\r
2067 CreateInElement (string1, string2, inside);
\r
2070 else if (FindEqualElement (s, lower, ref string1, ref string2))
\r
2071 CreateEqualsElement (string1, string2, inside);
\r
2074 else if (FindUnequalElement (s, lower, ref string1, ref string2))
\r
2075 CreateUnequalsElement (string1, string2, inside);
\r
2078 else if (FindLessThanOrEqualElement (s, lower, ref string1, ref string2))
\r
2079 CreateLessThanOrEqualElement (string1, string2, inside);
\r
2082 else if (FindLessThanElement (s, lower, ref string1, ref string2))
\r
2083 CreateLessThanElement (string1, string2, inside);
\r
2086 else if (FindGreaterThanOrEqualElement (s, lower, ref string1, ref string2))
\r
2087 CreateGreaterThanOrEqualElement (string1, string2, inside);
\r
2090 else if (FindGreaterThanElement (s, lower, ref string1, ref string2))
\r
2091 CreateGreaterThanElement (string1, string2, inside);
\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
2097 else if (FindMultiplyElement (s, lower, ref string1, ref string2))
\r
2098 CreateMultiplyElement (string1, string2, inside);
\r
2101 else if (FindDivideElement (s, lower, ref string1, ref string2))
\r
2102 CreateDivideElement (string1, string2, inside);
\r
2106 else if (FindAdditionElement (s, lower, ref string1, ref string2))
\r
2107 CreateAdditionElement (string1, string2, inside);
\r
2110 else if (FindSubtractElement (s, lower, ref string1, ref string2))
\r
2111 CreateSubtractionElement (string1, string2, inside);
\r
2114 else if (FindModulusElement (s, lower, ref string1, ref string2))
\r
2115 CreateModulusElement (string1, string2, inside);
\r
2118 else if (FindAggregateElement (s, lower, AGGREGATE.SUM))
\r
2119 Elements.Add (new ExpressionSum (s.Trim ()));
\r
2122 else if (FindAggregateElement (s, lower, AGGREGATE.AVG))
\r
2123 Elements.Add (new ExpressionAvg (s.Trim ()));
\r
2126 else if (FindAggregateElement (s, lower, AGGREGATE.MIN))
\r
2127 Elements.Add (new ExpressionMin (s.Trim ()));
\r
2130 else if (FindAggregateElement (s, lower, AGGREGATE.MAX))
\r
2131 Elements.Add (new ExpressionMax (s.Trim ()));
\r
2134 else if (FindAggregateElement (s, lower, AGGREGATE.COUNT))
\r
2135 Elements.Add (new ExpressionCount (s.Trim ()));
\r
2138 else if (FindAggregateElement (s, lower, AGGREGATE.STDEV))
\r
2139 Elements.Add (new ExpressionStdev (s.Trim ()));
\r
2142 else if (FindAggregateElement (s, lower, AGGREGATE.VAR))
\r
2143 Elements.Add (new ExpressionVar (s.Trim ()));
\r
2146 else if (FindLenElement (s, lower))
\r
2147 Elements.Add (new ExpressionLen (s.Trim ()));
\r
2150 else if (FindIifElement (s, lower))
\r
2151 Elements.Add (new ExpressionIif (s.Trim ()));
\r
2154 else if (FindIsNullElement (s, lower))
\r
2155 Elements.Add (new ExpressionIsNull (s.Trim ()));
\r
2158 else if (FindSubstringElement (s, lower))
\r
2159 Elements.Add (new ExpressionSubstring (s.Trim ()));
\r
2161 // if expression is like '(something someoperator something)'
\r
2162 else if (inside.Trim () != string.Empty)
\r
2163 ParseExpression (inside);
\r
2165 // At least, if it wasnt any of the above it is just normat string or int
\r
2168 Elements.Add (new ExpressionSingleElement (s.Trim ()));
\r
2171 #region CheckElement methods
\r
2174 // These methods are temporary for now
\r
2177 private bool FindOrElement (string s, string lower, ref string s1, ref string s2)
\r
2179 string stemp = lower;
\r
2180 int indexOf = stemp.IndexOf("or");
\r
2182 if (indexOf == -1)
\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
2190 oldIndex = indexOf;
\r
2192 // check is the 'or' element part of string element
\r
2193 if (IsPartOfStringElement (stemp, indexOf))
\r
2196 // Check is or part of something else for example column name
\r
2197 if (indexOf != 0)
\r
2200 if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')
\r
2204 if (indexOf < s.Length + 2)
\r
2207 if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')
\r
2211 if (IsPartOfFunction (stemp, indexOf))
\r
2214 s1 = s.Substring (0, indexOf).Trim ();
\r
2215 s2 = s.Substring (indexOf + 2).Trim ();
\r
2223 private bool FindAndElement (string s, string lower, ref string s1, ref string s2)
\r
2225 string stemp = lower;
\r
2226 int indexOf = stemp.IndexOf("and");
\r
2228 if (indexOf == -1)
\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
2236 oldIndex = indexOf;
\r
2238 // check is the 'and' element part of string element
\r
2239 if (IsPartOfStringElement (stemp, indexOf))
\r
2243 // Check is or part of something else for example column name
\r
2244 if (indexOf != 0)
\r
2247 if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')
\r
2251 if (indexOf < stemp.Length + 3)
\r
2254 if (stemp [indexOf + 3] != ' ' && stemp [indexOf + 3] != '\'')
\r
2258 if (IsPartOfFunction (stemp, indexOf))
\r
2262 s1 = s.Substring (0, indexOf).Trim ();
\r
2263 s2 = s.Substring (indexOf + 3).Trim ();
\r
2270 private bool FindLikeElement (string s, string lower, ref string s1, ref string s2)
\r
2272 string stemp = lower;
\r
2273 int indexOf = stemp.IndexOf("like");
\r
2275 if (indexOf == -1)
\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
2283 oldIndex = indexOf;
\r
2285 // check is the 'and' element part of string element
\r
2286 if (IsPartOfStringElement (stemp, indexOf))
\r
2290 // Check is or part of something else for example column name
\r
2291 if (indexOf != 0)
\r
2294 if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')
\r
2298 if (indexOf < stemp.Length + 4)
\r
2301 if (stemp [indexOf + 4] != ' ' && stemp [indexOf + 4] != '\'')
\r
2305 if (IsPartOfFunction (stemp, indexOf))
\r
2309 s1 = s.Substring (0, indexOf).Trim ();
\r
2310 s2 = s.Substring (indexOf + 4).Trim ();
\r
2317 private bool FindEqualElement (string s, string lower, ref string s1, ref string s2)
\r
2319 string stemp = lower;
\r
2320 int indexOf = stemp.IndexOf ("=");
\r
2322 if (indexOf == -1)
\r
2325 int oldIndex = -1;
\r
2327 while ((indexOf = stemp.IndexOf ("=", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2330 oldIndex = indexOf;
\r
2332 // Check is the = part of <= or >=
\r
2333 if (stemp [indexOf - 1] == '<' || stemp [indexOf - 1] == '>')
\r
2336 // Check is the = element part of string element
\r
2337 if (IsPartOfStringElement (stemp, indexOf))
\r
2340 // Check is or part of column name
\r
2341 if (IsPartOfColumnName (stemp, indexOf))
\r
2344 if (IsPartOfFunction (stemp, indexOf))
\r
2347 s1 = s.Substring (0, indexOf).Trim ();
\r
2348 s2 = s.Substring (indexOf + 1).Trim ();
\r
2356 private bool FindUnequalElement (string s, string lower, ref string s1, ref string s2)
\r
2358 string stemp = lower;
\r
2359 int indexOf = stemp.IndexOf ("<>");
\r
2361 if (stemp.IndexOf ("<>") == -1)
\r
2364 int oldIndex = -1;
\r
2365 while ((indexOf = stemp.IndexOf ("<>", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2368 oldIndex = indexOf;
\r
2370 // test if next charachter is something else than ' '
\r
2371 bool failed = false;
\r
2373 // Check is the <> element part of string element
\r
2374 if (IsPartOfStringElement (stemp, indexOf))
\r
2377 // Check is or part of column name
\r
2378 if (IsPartOfColumnName (stemp, indexOf))
\r
2381 if (IsPartOfFunction (stemp, indexOf))
\r
2384 s1 = s.Substring (0, indexOf).Trim ();
\r
2385 s2 = s.Substring (indexOf + 2).Trim ();
\r
2395 private bool FindLessThanElement (string s, string lower, ref string s1, ref string s2)
\r
2397 string stemp = lower;
\r
2398 int indexOf = stemp.IndexOf ("<");
\r
2400 if (indexOf == -1)
\r
2403 int oldIndex = -1;
\r
2404 while ((indexOf = stemp.IndexOf ("<", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2407 oldIndex = indexOf;
\r
2409 // if < is part of <> or <=
\r
2410 if (stemp [indexOf + 1] == '>' || stemp [indexOf + 1] == '=')
\r
2413 // Test is < element part of string element
\r
2414 if (IsPartOfStringElement (stemp, indexOf))
\r
2417 // Check is or part of column name
\r
2418 if (IsPartOfColumnName (stemp, indexOf))
\r
2421 if (IsPartOfFunction (stemp, indexOf))
\r
2424 s1 = s.Substring (0, indexOf).Trim ();
\r
2425 s2 = s.Substring (indexOf + 1).Trim ();
\r
2433 private bool FindLessThanOrEqualElement (string s, string lower, ref string s1, ref string s2)
\r
2435 string stemp = lower;
\r
2436 int indexOf = stemp.IndexOf ("<=");
\r
2438 if (indexOf == -1)
\r
2441 int oldIndex = -1;
\r
2442 while ((indexOf = stemp.IndexOf ("<=", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2445 oldIndex = indexOf;
\r
2446 // Test is <= element part of string element
\r
2447 if (IsPartOfStringElement (stemp, indexOf))
\r
2450 // Check is or part of column name
\r
2451 if (IsPartOfColumnName (stemp, indexOf))
\r
2454 if (IsPartOfFunction (stemp, indexOf))
\r
2457 s1 = s.Substring (0, indexOf).Trim ();
\r
2458 s2 = s.Substring (indexOf + 2).Trim ();
\r
2466 private bool FindGreaterThanElement (string s, string lower, ref string s1, ref string s2)
\r
2468 string stemp = lower;
\r
2469 int indexOf = stemp.IndexOf (">");
\r
2471 if (indexOf == -1)
\r
2474 int oldIndex = -1;
\r
2475 while ((indexOf = stemp.IndexOf (">", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2478 oldIndex = indexOf;
\r
2480 // if < is part of <> or <=
\r
2481 if (stemp [indexOf - 1] == '<' || stemp [indexOf + 1] == '=')
\r
2484 // Test is < element part of string element
\r
2485 if (IsPartOfStringElement (stemp, indexOf))
\r
2488 // Check is or part of column name
\r
2489 if (IsPartOfColumnName (stemp, indexOf))
\r
2492 if (IsPartOfFunction (stemp, indexOf))
\r
2495 s1 = s.Substring (0, indexOf).Trim ();
\r
2496 s2 = s.Substring (indexOf + 1).Trim ();
\r
2503 private bool FindGreaterThanOrEqualElement (string s, string lower, ref string s1, ref string s2)
\r
2505 string stemp = lower;
\r
2506 int indexOf = stemp.IndexOf (">=");
\r
2508 if (indexOf == -1)
\r
2511 int oldIndex = -1;
\r
2512 while ((indexOf = stemp.IndexOf (">=", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2515 oldIndex = indexOf;
\r
2516 bool failed = false;
\r
2517 // Test is <= element part of string element
\r
2519 // Check is or part of column name
\r
2520 if (IsPartOfColumnName (stemp, indexOf))
\r
2523 // is the element part of string element
\r
2524 if (IsPartOfStringElement (stemp, indexOf))
\r
2527 if (IsPartOfFunction (stemp, indexOf))
\r
2530 s1 = s.Substring (0, indexOf).Trim ();
\r
2531 s2 = s.Substring (indexOf + 2).Trim ();
\r
2539 private bool FindAdditionElement (string s, string lower, ref string s1, ref string s2)
\r
2541 string stemp = lower;
\r
2542 int indexOf = stemp.IndexOf ("+");
\r
2544 if (indexOf == -1)
\r
2547 int oldIndex = -1;
\r
2548 while ((indexOf = stemp.IndexOf ("+", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2551 // FIXME: if '+' represents sign of integer
\r
2553 oldIndex = indexOf;
\r
2554 bool failed = false;
\r
2556 // Check is or part of column name
\r
2557 if (IsPartOfColumnName (stemp, indexOf))
\r
2560 // is the element part of string element
\r
2561 if (IsPartOfStringElement (stemp, indexOf))
\r
2564 if (IsPartOfFunction (stemp, indexOf))
\r
2567 s1 = s.Substring (0, indexOf).Trim ();
\r
2568 s2 = s.Substring (indexOf + 1).Trim ();
\r
2576 private bool FindSubtractElement (string s, string lower, ref string s1, ref string s2)
\r
2578 string stemp = lower;
\r
2579 int indexOf = stemp.IndexOf ("-");
\r
2581 if (indexOf == -1)
\r
2584 int oldIndex = -1;
\r
2585 while ((indexOf = stemp.IndexOf ("-", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2588 oldIndex = indexOf;
\r
2589 bool failed = false;
\r
2591 // check is this lonely element
\r
2593 for (int i = indexOf - 1; i >= 0; i--)
\r
2595 if (stemp [i] != ' ')
\r
2605 // Check is or part of column name
\r
2606 if (IsPartOfColumnName (stemp, indexOf))
\r
2609 // is the element part of string element
\r
2610 if (IsPartOfStringElement (stemp, indexOf))
\r
2613 if (IsPartOfFunction (stemp, indexOf))
\r
2616 s1 = s.Substring (0, indexOf).Trim ();
\r
2617 s2 = s.Substring (indexOf + 1).Trim ();
\r
2625 private bool FindMultiplyElement (string s, string lower, ref string s1, ref string s2)
\r
2627 string stemp = lower;
\r
2628 int indexOf = stemp.IndexOf ("*");
\r
2630 if (indexOf == -1)
\r
2633 int oldIndex = -1;
\r
2634 while ((indexOf = stemp.IndexOf ("*", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2638 oldIndex = indexOf;
\r
2639 bool failed = false;
\r
2641 // FIXME: If there is a divide operator before multiply operator.
\r
2643 // Check is or part of column name
\r
2644 if (IsPartOfColumnName (stemp, indexOf))
\r
2647 // is the element part of string element
\r
2648 if (IsPartOfStringElement (stemp, indexOf))
\r
2651 if (IsPartOfFunction (stemp, indexOf))
\r
2654 s1 = s.Substring (0, indexOf).Trim ();
\r
2655 s2 = s.Substring (indexOf + 1).Trim ();
\r
2663 private bool FindDivideElement (string s, string lower, ref string s1, ref string s2)
\r
2665 string stemp = lower;
\r
2666 int indexOf = stemp.IndexOf ("/");
\r
2668 if (indexOf == -1)
\r
2671 int oldIndex = -1;
\r
2672 while ((indexOf = stemp.IndexOf ("/", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2676 oldIndex = indexOf;
\r
2677 bool failed = false;
\r
2679 // FIXME: If there is a multiply operator before divide operator.
\r
2681 // Check is or part of column name
\r
2682 if (IsPartOfColumnName (stemp, indexOf))
\r
2685 // is the element part of string element
\r
2686 if (IsPartOfStringElement (stemp, indexOf))
\r
2689 if (IsPartOfFunction (stemp, indexOf))
\r
2692 s1 = s.Substring (0, indexOf).Trim ();
\r
2693 s2 = s.Substring (indexOf + 1).Trim ();
\r
2701 private bool FindModulusElement (string s, string lower, ref string s1, ref string s2)
\r
2703 string stemp = lower;
\r
2704 int indexOf = stemp.IndexOf ("%");
\r
2706 if (indexOf == -1)
\r
2709 int oldIndex = -1;
\r
2710 while ((indexOf = stemp.IndexOf ("%", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2714 oldIndex = indexOf;
\r
2715 bool failed = false;
\r
2717 // FIXME: If there is a multiply operator before divide operator.
\r
2719 // Check is or part of column name
\r
2720 if (IsPartOfColumnName (stemp, indexOf))
\r
2723 // is the element part of string element
\r
2724 if (IsPartOfStringElement (stemp, indexOf))
\r
2727 s1 = s.Substring (0, indexOf).Trim ();
\r
2728 s2 = s.Substring (indexOf + 1).Trim ();
\r
2736 private bool FindAggregateElement (string s, string lower, AGGREGATE aggregate)
\r
2738 string agg = null;
\r
2740 switch (aggregate)
\r
2743 case AGGREGATE.SUM:
\r
2746 case AGGREGATE.AVG:
\r
2749 case AGGREGATE.MIN:
\r
2752 case AGGREGATE.MAX:
\r
2755 case AGGREGATE.COUNT:
\r
2758 case AGGREGATE.STDEV:
\r
2761 case AGGREGATE.VAR:
\r
2765 throw new NotImplementedException ();
\r
2769 string stemp = lower;
\r
2770 int indexOf = stemp.IndexOf (agg);
\r
2772 if (indexOf == -1)
\r
2775 int oldIndex = -1;
\r
2776 while ((indexOf = stemp.IndexOf (agg, oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2779 oldIndex = indexOf;
\r
2780 bool failed = false;
\r
2782 // Check is or part of column name
\r
2783 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2786 // is the element part of string element
\r
2787 if (IsPartOfStringElement (stemp, indexOf))
\r
2798 private bool FindSumElement (string s, string lower)
\r
2800 string stemp = lower;
\r
2801 int indexOf = stemp.IndexOf ("sum");
\r
2803 if (indexOf == -1)
\r
2806 int oldIndex = -1;
\r
2807 while ((indexOf = stemp.IndexOf ("sum", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2810 oldIndex = indexOf;
\r
2811 bool failed = false;
\r
2813 // Check is or part of column name
\r
2814 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2817 // is the element part of string element
\r
2818 if (IsPartOfStringElement (stemp, indexOf))
\r
2828 private bool FindAvgElement (string s, string lower)
\r
2830 string stemp = lower;
\r
2831 int indexOf = stemp.IndexOf ("avg");
\r
2833 if (indexOf == -1)
\r
2836 int oldIndex = -1;
\r
2837 while ((indexOf = stemp.IndexOf ("avg", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2840 oldIndex = indexOf;
\r
2841 bool failed = false;
\r
2843 // Check is or part of column name
\r
2844 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2847 // is the element part of string element
\r
2848 if (IsPartOfStringElement (stemp, indexOf))
\r
2857 private bool FindMinElement (string s, string lower)
\r
2859 string stemp = lower;
\r
2860 int indexOf = stemp.IndexOf ("min");
\r
2862 if (indexOf == -1)
\r
2865 int oldIndex = -1;
\r
2866 while ((indexOf = stemp.IndexOf ("min", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2869 oldIndex = indexOf;
\r
2870 bool failed = false;
\r
2872 // Check is or part of column name
\r
2873 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2876 // is the element part of string element
\r
2877 if (IsPartOfStringElement (stemp, indexOf))
\r
2886 private bool FindMaxElement (string s, string lower)
\r
2888 string stemp = lower;
\r
2889 int indexOf = stemp.IndexOf ("max");
\r
2891 if (indexOf == -1)
\r
2894 int oldIndex = -1;
\r
2895 while ((indexOf = stemp.IndexOf ("max", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2898 oldIndex = indexOf;
\r
2899 bool failed = false;
\r
2901 // Check is or part of column name
\r
2902 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2905 // is the element part of string element
\r
2906 if (IsPartOfStringElement (stemp, indexOf))
\r
2915 private bool FindCountElement (string s, string lower)
\r
2917 string stemp = lower;
\r
2918 int indexOf = stemp.IndexOf ("count");
\r
2920 if (indexOf == -1)
\r
2923 int oldIndex = -1;
\r
2924 while ((indexOf = stemp.IndexOf ("count", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2927 oldIndex = indexOf;
\r
2928 bool failed = false;
\r
2930 // Check is or part of column name
\r
2931 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2934 // is the element part of string element
\r
2935 if (IsPartOfStringElement (stemp, indexOf))
\r
2944 private bool FindStdevElement (string s, string lower)
\r
2946 string stemp = lower;
\r
2947 int indexOf = stemp.IndexOf ("stdev");
\r
2949 if (indexOf == -1)
\r
2952 int oldIndex = -1;
\r
2953 while ((indexOf = stemp.IndexOf ("stdev", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2956 oldIndex = indexOf;
\r
2957 bool failed = false;
\r
2959 // Check is or part of column name
\r
2960 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2963 // is the element part of string element
\r
2964 if (IsPartOfStringElement (stemp, indexOf))
\r
2973 private bool FindVarElement (string s, string lower)
\r
2975 string stemp = lower;
\r
2976 int indexOf = stemp.IndexOf ("var");
\r
2978 if (indexOf == -1)
\r
2981 int oldIndex = -1;
\r
2982 while ((indexOf = stemp.IndexOf ("var", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
2985 oldIndex = indexOf;
\r
2986 bool failed = false;
\r
2988 // Check is or part of column name
\r
2989 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
2992 // is the element part of string element
\r
2993 if (IsPartOfStringElement (stemp, indexOf))
\r
3002 private bool FindLenElement (string s, string lower)
\r
3004 string stemp = lower;
\r
3005 int indexOf = stemp.IndexOf ("len");
\r
3007 if (indexOf == -1)
\r
3010 int oldIndex = -1;
\r
3011 while ((indexOf = stemp.IndexOf ("len", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
3014 oldIndex = indexOf;
\r
3015 bool failed = false;
\r
3017 // Check is or part of column name
\r
3018 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
3021 // is the element part of string element
\r
3022 if (IsPartOfStringElement (stemp, indexOf))
\r
3032 private bool FindIifElement (string s, string lower)
\r
3034 string stemp = lower;
\r
3035 int indexOf = stemp.IndexOf ("iif");
\r
3037 if (indexOf == -1)
\r
3040 int oldIndex = -1;
\r
3041 while ((indexOf = stemp.IndexOf ("iif", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
3044 oldIndex = indexOf;
\r
3045 bool failed = false;
\r
3047 // Check is or part of column name
\r
3048 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
3051 // is the element part of string element
\r
3052 if (IsPartOfStringElement (stemp, indexOf))
\r
3061 private bool FindIsNullElement (string s, string lower)
\r
3063 string stemp = lower;
\r
3064 int indexOf = stemp.IndexOf ("isnull");
\r
3066 if (indexOf == -1)
\r
3069 int oldIndex = -1;
\r
3070 while ((indexOf = stemp.IndexOf ("isnull", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
3073 oldIndex = indexOf;
\r
3074 bool failed = false;
\r
3076 // Check is or part of column name
\r
3077 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
3080 // is the element part of string element
\r
3081 if (IsPartOfStringElement (stemp, indexOf))
\r
3090 private bool FindSubstringElement (string s, string lower)
\r
3092 string stemp = lower;
\r
3093 int indexOf = stemp.IndexOf ("substring");
\r
3095 if (indexOf == -1)
\r
3098 int oldIndex = -1;
\r
3099 while ((indexOf = stemp.IndexOf ("substring", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
3102 oldIndex = indexOf;
\r
3103 bool failed = false;
\r
3105 // Check is or part of column name
\r
3106 if (indexOf != 0 && stemp [indexOf - 1] != ' ')
\r
3109 // is the element part of string element
\r
3110 if (IsPartOfStringElement (stemp, indexOf))
\r
3119 private bool FindInElement (string s, string lower, ref string s1, ref string s2)
\r
3121 string stemp = lower;
\r
3122 int indexOf = stemp.IndexOf ("in");
\r
3124 if (indexOf == -1)
\r
3127 int oldIndex = -1;
\r
3128 while ((indexOf = stemp.IndexOf ("in", oldIndex + 1)) != -1 && indexOf > oldIndex)
\r
3130 oldIndex = indexOf;
\r
3132 // check is the 'and' element part of string element
\r
3133 if (IsPartOfStringElement (stemp, indexOf))
\r
3137 // Check is or part of something else for example column name
\r
3138 if (indexOf != 0)
\r
3140 if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')
\r
3144 if (indexOf < stemp.Length + 2)
\r
3146 if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')
\r
3150 if (IsPartOfFunction (stemp, indexOf))
\r
3153 s1 = s.Substring (0, indexOf).Trim ();
\r
3154 s2 = s.Substring (indexOf + 2).Trim ();
\r
3162 #endregion // CheckElement methods
\r
3164 #region CreateElement methods
\r
3167 // These methods are going to be removed when way of parsing is changed
\r
3170 private void CreateOrElement (string s1, string s2, string inside)
\r
3172 CheckParenthesis (inside, ref s1, ref s2);
\r
3173 Elements.Add (new ExpressionOr (s1.Trim (), s2.Trim ()));
\r
3176 private void CreateAndElement (string s1, string s2, string inside)
\r
3178 CheckParenthesis (inside, ref s1, ref s2);
\r
3179 Elements.Add (new ExpressionAnd (s1.Trim (), s2.Trim ()));
\r
3182 private void CreateLikeElement (string s1, string s2, string inside)
\r
3184 CheckParenthesis (inside, ref s1, ref s2);
\r
3185 Elements.Add (new ExpressionLike (s1.Trim (), s2.Trim ()));
\r
3188 private void CreateInElement (string s1, string s2, string inside)
\r
3190 CheckParenthesis (inside, ref s1, ref s2);
\r
3191 Elements.Add (new ExpressionIn (s1.Trim (), s2.Trim ()));
\r
3194 private void CreateEqualsElement (string s1, string s2, string inside)
\r
3196 CheckParenthesis (inside, ref s1, ref s2);
\r
3197 Elements.Add (new ExpressionEquals (s1.Trim (), s2.Trim ()));
\r
3200 private void CreateUnequalsElement (string s1, string s2, string inside)
\r
3202 CheckParenthesis (inside, ref s1, ref s2);
\r
3203 Elements.Add (new ExpressionUnequals (s1.Trim (), s2.Trim ()));
\r
3206 private void CreateLessThanElement (string s1, string s2, string inside)
\r
3208 CheckParenthesis (inside, ref s1, ref s2);
\r
3209 Elements.Add (new ExpressionLessThan (s1.Trim (), s2.Trim ()));
\r
3212 private void CreateLessThanOrEqualElement (string s1, string s2, string inside)
\r
3214 CheckParenthesis (inside, ref s1, ref s2);
\r
3215 Elements.Add (new ExpressionLessThanOrEqual (s1.Trim (), s2.Trim ()));
\r
3218 private void CreateGreaterThanElement (string s1, string s2, string inside)
\r
3220 CheckParenthesis (inside, ref s1, ref s2);
\r
3221 Elements.Add (new ExpressionGreaterThan (s1.Trim (), s2.Trim ()));
\r
3225 private void CreateGreaterThanOrEqualElement (string s1, string s2, string inside)
\r
3227 CheckParenthesis (inside, ref s1, ref s2);
\r
3228 Elements.Add (new ExpressionGreaterThanOrEqual (s1.Trim (), s2.Trim ()));
\r
3231 private void CreateAdditionElement (string s1, string s2, string inside)
\r
3233 CheckParenthesis (inside, ref s1, ref s2);
\r
3234 Elements.Add (new ExpressionAddition (s1.Trim (), s2.Trim ()));
\r
3237 private void CreateSubtractionElement (string s1, string s2, string inside)
\r
3239 CheckParenthesis (inside, ref s1, ref s2);
\r
3240 Elements.Add (new ExpressionSubtraction (s1.Trim (), s2.Trim ()));
\r
3243 private void CreateMultiplyElement (string s1, string s2, string inside)
\r
3245 CheckParenthesis (inside, ref s1, ref s2);
\r
3246 Elements.Add (new ExpressionMultiply (s1.Trim (), s2.Trim ()));
\r
3249 private void CreateDivideElement (string s1, string s2, string inside)
\r
3251 CheckParenthesis (inside, ref s1, ref s2);
\r
3252 Elements.Add (new ExpressionDivide (s1.Trim (), s2.Trim ()));
\r
3255 private void CreateModulusElement (string s1, string s2, string inside)
\r
3257 CheckParenthesis (inside, ref s1, ref s2);
\r
3258 Elements.Add (new ExpressionModulus (s1.Trim (), s2.Trim ()));
\r
3261 #endregion // CreateElemnt methods
\r
3263 #region Little helppers
\r
3265 private void CheckParenthesis (string inside, ref string s1, ref string s2)
\r
3267 if (s1 == string.Empty && inside != string.Empty)
\r
3269 else if (s2 == string.Empty && inside != string.Empty)
\r
3275 /// Checks is the element part of stringelement
\r
3277 private bool IsPartOfStringElement (string s, int indexOf)
\r
3279 // count how many '-charachters are before or. If count is odd it means or IS between quotes
\r
3281 for (int i = indexOf - 1; i >= 0; i--)
\r
3283 if (s [i] == '\'')
\r
3287 if ((quotes & 1) != 0)
\r
3294 /// Checks is the element part of column table
\r
3296 private bool IsPartOfColumnName (string s, int indexOf)
\r
3298 for (int i = indexOf; i >= 0; i--)
\r
3301 // If the element is between [] it is part of columnname
\r
3302 if (s [i] == '\'' || s [i] == ']')
\r
3306 else if (s [i] == '[')
\r
3317 /// Checks are element part of function
\r
3319 private bool IsPartOfFunction (string s, int indexOf)
\r
3323 // If ',' or '\'' comes before '(' this element is not part of function's parameters
\r
3326 for (int i = indexOf; i >= 0; i--)
\r
3329 if (s [i] == '(' || s [i] == ',')
\r
3333 else if (s [i] == ')')
\r
3342 #endregion // Little helppers
\r
3344 #region ExpressionElementComparer
\r
3345 protected sealed class ExpressionElementComparer
\r
3347 object _value1 = null;
\r
3350 DataRow _row = null;
\r
3352 public ExpressionElementComparer(ExpressionElement E1, DataRow Row)
\r
3354 _value1 = E1.Result (Row);
\r
3358 if (_value1 == null || _value1 == DBNull.Value)
\r
3361 _t1 = _value1.GetType ();
\r
3362 _RT1 = E1.ResultType (Row);
\r
3365 public int CompareTo (ExpressionElement E2)
\r
3367 object value1 = _value1;
\r
3368 object value2 = E2.Result (_row);
\r
3370 if ((value1 == null || value1 == DBNull.Value) && (value2 == null || value2 == DBNull.Value))
\r
3372 else if (value2 == null || value2 == DBNull.Value)
\r
3374 else if (value1 == null || value1 == DBNull.Value)
\r
3377 Type t2 = value2.GetType ();
\r
3379 Type RT2 = E2.ResultType (_row);
\r
3381 if (_t1 == typeof (string) || t2 == typeof (string))
\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
3389 value2 = Convert.ChangeType (value2, Type.GetTypeCode (_t1));
\r
3392 if (value1 is IComparable)
\r
3393 return ((IComparable)value1).CompareTo(value2);
\r
3395 return (int) _t1.InvokeMember ("CompareTo", BindingFlags.Default |
\r
3396 BindingFlags.InvokeMethod, null,
\r
3398 new object [] {value2});
\r