--- /dev/null
+//\r
+// System.Data.ExpressionElement \r
+//\r
+// Author:\r
+// Ville Palo <vi64pa@kolumbus.fi>\r
+//\r
+// Copyright (C) Ville Palo, 2003\r
+//\r
+// TODO: - Some functionelements and aggregates.\r
+// - New parsing style.\r
+// - Exceptions\r
+//\r
+\r
+using System;\r
+using System.Data;\r
+using System.Reflection;\r
+\r
+using System.Collections;\r
+using System.Text;\r
+\r
+namespace System.Data\r
+{\r
+#if false\r
+ /// <summary>\r
+ /// The main element which includes whole expression\r
+ /// </summary>\r
+ internal class ExpressionMainElement : ExpressionElement\r
+ {\r
+ \r
+ \r
+\r
+ public ExpressionMainElement (string s)\r
+ {\r
+ s = ExpressionElement.ValidateExpression (s);\r
+ ParseExpression (s);\r
+ }\r
+ \r
+ public override bool Test (DataRow Row) \r
+ {\r
+\r
+ foreach (ExpressionElement El in Elements) \r
+ {\r
+ if (!El.Test (Row))\r
+ return false;\r
+ }\r
+ \r
+ return true;\r
+ }\r
+\r
+ \r
+ }\r
+\r
+ //\r
+ // O_P_E_R_A_T_O_R_S\r
+ //\r
+\r
+ /// <summary>\r
+ /// Class for =\r
+ /// </summary>\r
+ internal class ExpressionEquals : ExpressionElement\r
+ { \r
+\r
+ public ExpressionEquals (string exp1, string exp2) \r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+ \r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+ return ExpressionElement.Compare (E1, E2, Row) == 0;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for <\r
+ /// </summary>\r
+ internal class ExpressionLessThan : ExpressionElement\r
+ { \r
+\r
+ public ExpressionLessThan (string exp1, string exp2) \r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+ \r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+ \r
+ return ExpressionElement.Compare (E1, E2, Row) < 0;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for <=\r
+ /// </summary>\r
+ internal class ExpressionLessThanOrEqual : ExpressionElement\r
+ { \r
+\r
+ public ExpressionLessThanOrEqual (string exp1, string exp2) \r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+ return ExpressionElement.Compare (E1, E2, Row) <= 0;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for >\r
+ /// </summary>\r
+ internal class ExpressionGreaterThan : ExpressionElement\r
+ { \r
+\r
+ public ExpressionGreaterThan (string exp1, string exp2) \r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+ \r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+ return ExpressionElement.Compare (E1, E2, Row) > 0;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for >=\r
+ /// </summary>\r
+ internal class ExpressionGreaterThanOrEqual : ExpressionElement\r
+ { \r
+\r
+ public ExpressionGreaterThanOrEqual (string exp1, string exp2) \r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+ return ExpressionElement.Compare (E1, E2, Row) >= 0;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for <>\r
+ /// </summary>\r
+ internal class ExpressionUnequals : ExpressionElement\r
+ { \r
+\r
+ public ExpressionUnequals (string exp1, string exp2) \r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+ \r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+ return ExpressionElement.Compare (E1, E2, Row) != 0;\r
+ }\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Class for LIKE-operator\r
+ /// </summary>\r
+ internal class ExpressionLike : ExpressionElement\r
+ { \r
+\r
+ public ExpressionLike (string exp1, string exp2) \r
+ {\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+ object value1 = E1.Result (Row);\r
+ object value2 = E2.Result (Row);\r
+ \r
+ if (value1.GetType () != typeof (string) || value2.GetType () != typeof (string))\r
+ throw new Exception (); // TODO: what exception\r
+ \r
+ string operand1 = value1.ToString ();\r
+ string operand2 = value2.ToString ();\r
+\r
+ // find out is there wildcards like * or %.\r
+ while (operand2.EndsWith ("*") || operand2.EndsWith ("%")) \r
+ operand2 = operand2.Remove (operand2.Length - 1, 1);\r
+ while (operand2.StartsWith ("*") || operand2.StartsWith ("%"))\r
+ operand2 = operand2.Remove (0, 1);\r
+\r
+ int oldIndex = 0;\r
+ int indexOf = -1;\r
+\r
+ indexOf = operand2.IndexOf ("*");\r
+ while (indexOf != -1) \r
+ {\r
+\r
+ oldIndex = indexOf + 1;\r
+ if (operand2 [indexOf + 1] != ']' || operand2 [indexOf - 1] != '[')\r
+ throw new EvaluateException ("Error in Like operator: ther string pattern " + operand1 + " is invalid");\r
+ else \r
+ {\r
+ operand2 = operand2.Remove (indexOf + 1, 1);\r
+ operand2 = operand2.Remove (indexOf -1, 1);\r
+ oldIndex--;\r
+ }\r
+ \r
+ indexOf = operand2.IndexOf ("*", oldIndex);\r
+ }\r
+\r
+ oldIndex = 0;\r
+ indexOf = operand2.IndexOf ("%");\r
+ while (indexOf != -1) \r
+ {\r
+\r
+ oldIndex = indexOf + 1;\r
+ \r
+ if (operand2 [indexOf + 1] != ']' || operand2 [indexOf - 1] != '[')\r
+ throw new EvaluateException ("Error in Like operator: ther string pattern " + operand2 + " is invalid");\r
+ else \r
+ {\r
+ operand2 = operand2.Remove (indexOf + 1, 1);\r
+ operand2 = operand2.Remove (indexOf -1, 1); \r
+ oldIndex--;\r
+ }\r
+\r
+ indexOf = operand2.IndexOf ("%", oldIndex);\r
+ }\r
+\r
+ int len2 = operand2.Length;\r
+ int startIndex = 0;\r
+ while ((startIndex + len2) <= operand1.Length) \r
+ {\r
+ if (String.Compare (operand1.Substring (startIndex, len2), operand2, !Row.Table.CaseSensitive) == 0)\r
+ return true;\r
+ startIndex++;\r
+ }\r
+\r
+ return false;\r
+ }\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Class for OR\r
+ /// </summary>\r
+ internal class ExpressionOr : ExpressionElement\r
+ { \r
+ public ExpressionOr (string exp1, string exp2)\r
+ {\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ { \r
+ foreach (ExpressionElement El in Elements) \r
+ {\r
+ if (El.Test (Row))\r
+ return true;\r
+ }\r
+ \r
+ return false;\r
+ } \r
+ }\r
+ \r
+ /// <summary>\r
+ /// Class for AND\r
+ /// </summary>\r
+ internal class ExpressionAnd : ExpressionElement\r
+ { \r
+ public ExpressionAnd (string exp1, string exp2)\r
+ {\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+ \r
+ public override object Result (DataRow Row) \r
+ {\r
+ \r
+ return Test(Row);\r
+ }\r
+\r
+ public override bool Test (DataRow Row) \r
+ {\r
+ foreach (ExpressionElement El in Elements) \r
+ {\r
+ if (!El.Test (Row))\r
+ return false;\r
+ }\r
+ \r
+ return true;\r
+ } \r
+ }\r
+\r
+\r
+ //\r
+ // A_R_I_T_H_M_E_T_I_C O_P_E_R_A_T_O_R_S\r
+ //\r
+\r
+ /// <summary>\r
+ /// Class for +\r
+ /// </summary>\r
+ internal class ExpressionAddition : ExpressionElement\r
+ {\r
+ public ExpressionAddition (string exp1, string exp2)\r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+ \r
+ public override Type ResultType (DataRow Row)\r
+ {\r
+ Type ResultType = typeof (string);\r
+ ExpressionElement exp1Temp = ((ExpressionElement)Elements [0]);\r
+ ExpressionElement exp2Temp = ((ExpressionElement)Elements [1]);\r
+\r
+ if (exp1Temp.ResultType (Row) == typeof (string) || exp2Temp.ResultType (Row) == typeof (string))\r
+ ResultType = typeof (string);\r
+\r
+ else if (exp1Temp.ResultType (Row) == typeof (long) || exp2Temp.ResultType (Row) == typeof (long))\r
+ ResultType = typeof (long);\r
+\r
+ else if (exp1Temp.ResultType (Row) == typeof (int) || exp2Temp.ResultType (Row) == typeof (int))\r
+ ResultType = typeof (int);\r
+\r
+ return ResultType;\r
+ }\r
+\r
+ public override object Result (DataRow Row) \r
+ {\r
+ return CalculateResult (Row);\r
+ }\r
+ \r
+ protected override object Calculate (object value1, object value2, Type TempType) \r
+ {\r
+ object Result = null; \r
+\r
+ if (TempType == typeof (string))\r
+ Result = (string)value1 + (string)value2;\r
+ else if (TempType == typeof (long))\r
+ Result = (long)value1 + (long)value2;\r
+ else if (TempType == typeof (int))\r
+ Result = (int)value1 + (int)value2;\r
+ else if (TempType == typeof (short))\r
+ Result = (short)value1 + (short)value2;\r
+ else if (TempType == typeof (ulong))\r
+ Result = (ulong)value1 + (ulong)value2;\r
+ else if (TempType == typeof (uint))\r
+ Result = (uint)value1 + (uint)value2;\r
+ else if (TempType == typeof (ushort))\r
+ Result = (ushort)value1 + (ushort)value2;\r
+ else if (TempType == typeof (byte))\r
+ Result = (byte)value1 + (byte)value2;\r
+ else if (TempType == typeof (sbyte))\r
+ Result = (sbyte)value1 + (sbyte)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (bool))\r
+ // Result = (bool)value1 + (bool)value2;\r
+ else if (TempType == typeof (float))\r
+ Result = (float)value1 + (float)value2;\r
+ else if (TempType == typeof (double))\r
+ Result = (double)value1 + (double)value2;\r
+ else if (TempType == typeof (decimal))\r
+ Result = (decimal)value1 + (decimal)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (DateTime))\r
+ // Result = (DateTime)value1 + (DateTime)value2;\r
+ \r
+ return Result;\r
+ }\r
+\r
+\r
+ // This method is shouldnt never invoked\r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for -\r
+ /// </summary>\r
+ internal class ExpressionSubtraction : ExpressionElement\r
+ {\r
+ public ExpressionSubtraction (string exp1, string exp2)\r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+ \r
+ public override object Result (DataRow Row) \r
+ { \r
+ return CalculateResult (Row);\r
+ }\r
+ \r
+ // This method is shouldnt never invoked\r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ protected override object Calculate (object value1, object value2, Type TempType) \r
+ {\r
+ object Result = null; \r
+\r
+ // FIXME:\r
+ //if (TempType == typeof (string))\r
+ // Result = (string)value1 - (string)value2;\r
+ if (TempType == typeof (long))\r
+ Result = (long)value1 - (long)value2;\r
+ else if (TempType == typeof (int))\r
+ Result = (int)value1 - (int)value2;\r
+ else if (TempType == typeof (short))\r
+ Result = (short)value1 - (short)value2;\r
+ else if (TempType == typeof (ulong))\r
+ Result = (ulong)value1 + (ulong)value2;\r
+ else if (TempType == typeof (uint))\r
+ Result = (uint)value1 - (uint)value2;\r
+ else if (TempType == typeof (ushort))\r
+ Result = (ushort)value1 - (ushort)value2;\r
+ else if (TempType == typeof (byte))\r
+ Result = (byte)value1 - (byte)value2;\r
+ else if (TempType == typeof (sbyte))\r
+ Result = (sbyte)value1 - (sbyte)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (bool))\r
+ // Result = (bool)value1 - (bool)value2;\r
+ else if (TempType == typeof (float))\r
+ Result = (float)value1 - (float)value2;\r
+ else if (TempType == typeof (double))\r
+ Result = (double)value1 - (double)value2;\r
+ else if (TempType == typeof (decimal))\r
+ Result = (decimal)value1 - (decimal)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (DateTime))\r
+ // Result = (DateTime)value1 - (DateTime)value2;\r
+ \r
+ return Result;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for *\r
+ /// </summary>\r
+ internal class ExpressionMultiply : ExpressionElement\r
+ {\r
+ public ExpressionMultiply (string exp1, string exp2)\r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+ \r
+ public override Type ResultType (DataRow Row)\r
+ {\r
+ Type ResultType = null;\r
+ ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+ ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+ Type t1 = E1.ResultType (Row);\r
+ Type t2 = E2.ResultType (Row);\r
+ \r
+ if (t1 == typeof (string) || t2 == typeof (string))\r
+ throw new EvaluateException ("Cannon perform '*' operation on " + t1.ToString () + \r
+ " and " + t2.ToString ());\r
+\r
+ else if (t1 == typeof (long) || t2 == typeof (long))\r
+ ResultType = typeof (long);\r
+\r
+ else if (t1 == typeof (int) || t2 == typeof (int))\r
+ ResultType = typeof (int);\r
+\r
+ return ResultType;\r
+ }\r
+\r
+ public override object Result (DataRow Row) \r
+ {\r
+ return CalculateResult (Row);\r
+ }\r
+ \r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ protected override object Calculate (object value1, object value2, Type TempType) \r
+ {\r
+ object Result = null; \r
+\r
+ if (TempType == typeof (long))\r
+ Result = (long)value1 * (long)value2;\r
+ else if (TempType == typeof (int))\r
+ Result = (int)value1 * (int)value2;\r
+ else if (TempType == typeof (short))\r
+ Result = (short)value1 * (short)value2;\r
+ else if (TempType == typeof (ulong))\r
+ Result = (ulong)value1 * (ulong)value2;\r
+ else if (TempType == typeof (uint))\r
+ Result = (uint)value1 * (uint)value2;\r
+ else if (TempType == typeof (ushort))\r
+ Result = (ushort)value1 * (ushort)value2;\r
+ else if (TempType == typeof (byte))\r
+ Result = (byte)value1 * (byte)value2;\r
+ else if (TempType == typeof (sbyte))\r
+ Result = (sbyte)value1 * (sbyte)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (bool))\r
+ // Result = (bool)value1 * (bool)value2;\r
+ else if (TempType == typeof (float))\r
+ Result = (float)value1 * (float)value2;\r
+ else if (TempType == typeof (double))\r
+ Result = (double)value1 * (double)value2;\r
+ else if (TempType == typeof (decimal))\r
+ Result = (decimal)value1 * (decimal)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (DateTime))\r
+ // Result = (DateTime)value1 * (DateTime)value2;\r
+ \r
+ return Result;\r
+ }\r
+\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for *\r
+ /// </summary>\r
+ internal class ExpressionDivide : ExpressionElement\r
+ {\r
+ public ExpressionDivide (string exp1, string exp2)\r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+ \r
+ public override object Result (DataRow Row) \r
+ {\r
+ return CalculateResult (Row);\r
+ }\r
+ \r
+ // This method is shouldnt never invoked\r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ protected override object Calculate (object value1, object value2, Type TempType) \r
+ {\r
+ object Result = null; \r
+\r
+ if (TempType == typeof (long))\r
+ Result = (long)value1 / (long)value2;\r
+ // FIXME: \r
+ //else if (TempType == typeof (int))\r
+ // Result = (string)value1 / (string)value2;\r
+ else if (TempType == typeof (int))\r
+ Result = (int)value1 / (int)value2;\r
+ else if (TempType == typeof (short))\r
+ Result = (short)value1 / (short)value2;\r
+ else if (TempType == typeof (ulong))\r
+ Result = (ulong)value1 / (ulong)value2;\r
+ else if (TempType == typeof (uint))\r
+ Result = (uint)value1 / (uint)value2;\r
+ else if (TempType == typeof (ushort))\r
+ Result = (ushort)value1 / (ushort)value2;\r
+ else if (TempType == typeof (byte))\r
+ Result = (byte)value1 / (byte)value2;\r
+ else if (TempType == typeof (sbyte))\r
+ Result = (sbyte)value1 / (sbyte)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (bool))\r
+ // Result = (bool)value1 // (bool)value2;\r
+ else if (TempType == typeof (float))\r
+ Result = (float)value1 / (float)value2;\r
+ else if (TempType == typeof (double))\r
+ Result = (double)value1 / (double)value2;\r
+ else if (TempType == typeof (decimal))\r
+ Result = (decimal)value1 / (decimal)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (DateTime))\r
+ // Result = (DateTime)value1 / (DateTime)value2;\r
+ \r
+ return Result;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for *\r
+ /// </summary>\r
+ internal class ExpressionModulus : ExpressionElement\r
+ {\r
+ public ExpressionModulus (string exp1, string exp2)\r
+ { \r
+ this.exp1 = exp1;\r
+ this.exp2 = exp2;\r
+ ParseExpression (exp1);\r
+ ParseExpression (exp2);\r
+ }\r
+ \r
+ public override object Result (DataRow Row) \r
+ {\r
+ return CalculateResult (Row);\r
+ }\r
+ \r
+ // This method is shouldnt never invoked\r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ protected override object Calculate (object value1, object value2, Type TempType) \r
+ {\r
+ object Result = null; \r
+\r
+ if (TempType == typeof (long))\r
+ Result = (long)value1 % (long)value2;\r
+ // FIXME: \r
+ //else if (TempType == typeof (int))\r
+ // Result = (string)value1 % (string)value2;\r
+ else if (TempType == typeof (int))\r
+ Result = (int)value1 % (int)value2;\r
+ else if (TempType == typeof (short))\r
+ Result = (short)value1 % (short)value2;\r
+ else if (TempType == typeof (ulong))\r
+ Result = (ulong)value1 % (ulong)value2;\r
+ else if (TempType == typeof (uint))\r
+ Result = (uint)value1 % (uint)value2;\r
+ else if (TempType == typeof (ushort))\r
+ Result = (ushort)value1 % (ushort)value2;\r
+ else if (TempType == typeof (byte))\r
+ Result = (byte)value1 % (byte)value2;\r
+ else if (TempType == typeof (sbyte))\r
+ Result = (sbyte)value1 % (sbyte)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (bool))\r
+ // Result = (bool)value1 // (bool)value2;\r
+ else if (TempType == typeof (float))\r
+ Result = (float)value1 % (float)value2;\r
+ else if (TempType == typeof (double))\r
+ Result = (double)value1 % (double)value2;\r
+ else if (TempType == typeof (decimal))\r
+ Result = (decimal)value1 % (decimal)value2;\r
+ // FIXME:\r
+ //else if (TempType == typeof (DateTime))\r
+ // Result = (DateTime)value1 / (DateTime)value2;\r
+ \r
+ return Result;\r
+ }\r
+ }\r
+\r
+ //\r
+ // _____A_G_G_R_E_G_A_T_E_S_____\r
+ //\r
+\r
+ internal class ExpressionAggregate : ExpressionElement\r
+ {\r
+ \r
+ public ExpressionAggregate()\r
+ {\r
+ }\r
+\r
+ public ExpressionAggregate(string s)\r
+ {\r
+ s = ExpressionElement.ValidateExpression (s);\r
+ ParseExpression (s);\r
+ }\r
+\r
+ \r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ public override object Result(DataRow Row)\r
+ {\r
+ DataRow[] rows = new DataRow[Row.Table.Rows.Count];\r
+ Row.Table.Rows.CopyTo(rows, 0);\r
+ return ((ExpressionAggregate)Elements[0]).Result(rows);\r
+ }\r
+\r
+ public virtual object Result(DataRow[] rows)\r
+ {\r
+ return ((ExpressionAggregate)Elements[0]).Result(rows);\r
+ }\r
+\r
+\r
+ protected virtual void ParseParameters (string s)\r
+ {\r
+ string stemp = s.ToLower ();\r
+ bool inString = false;\r
+ string p1 = null;\r
+\r
+ // find (\r
+ while (!s.StartsWith ("("))\r
+ s = s.Remove (0, 1);\r
+ \r
+ // remove (\r
+ s = s.Remove (0, 1);\r
+\r
+ int parentheses = 0;\r
+ for (int i = 0; i < s.Length; i++) \r
+ {\r
+\r
+ if (s [i] == '\'')\r
+ inString = !inString;\r
+ else if (s [i] == '(')\r
+ parentheses++;\r
+ else if (s [i] == ')')\r
+ parentheses--;\r
+\r
+ if ((s [i] == ',' || s [i] == ')') && !inString && parentheses == -1) \r
+ { // Parameter changed\r
+\r
+ if (p1 == null) \r
+ {\r
+ p1 = s.Substring (0, i);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (p1 == null)\r
+ throw new Exception ();\r
+\r
+ ParseExpression (p1); \r
+ }\r
+ \r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for Sum (column_Name)\r
+ /// </summary\r
+ internal class ExpressionSum : ExpressionAggregate\r
+ {\r
+ public ExpressionSum (string exp1)\r
+ {\r
+ ParseParameters (exp1);\r
+ }\r
+\r
+ public override object Result(DataRow[] rows)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ object value1 = E1.Result (rows[0]);\r
+ Type t1 = value1.GetType ();\r
+ object result = 0;\r
+ \r
+ // This could be optimized. If E1 is single element (Not child or parent) the\r
+ // result of Sum() aggregate is allways same\r
+\r
+ if (E1 is ExpressionSingleElement) \r
+ {\r
+ \r
+ // This should be optimized somehow\r
+ for (int i = 0; i < rows.Length; i++) \r
+ {\r
+\r
+ // TODO: other types and exceptions\r
+ object v = E1.Result (rows[i]);\r
+ t1 = v.GetType ();\r
+\r
+ if (v == null || v == DBNull.Value)\r
+ continue;\r
+\r
+ if (t1 == typeof (long)) \r
+ {\r
+ result = (long)result + (long)v;\r
+ }\r
+ else if (t1 == typeof (int)) \r
+ {\r
+ result = (int)result + (int)v;\r
+ }\r
+ else if (t1 == typeof (short)) \r
+ {\r
+ result = (short)result + (short)v;\r
+ }\r
+ else if (t1 == typeof (double)) \r
+ {\r
+ result = (double)result + (double)v;\r
+ }\r
+ else if (t1 == typeof (float)) \r
+ {\r
+ result = (float)result + (float)v;\r
+ }\r
+ else\r
+ throw new NotImplementedException ();\r
+ }\r
+ }\r
+ \r
+ return result;\r
+ }\r
+\r
+ \r
+ //\r
+ // Copy: This method is copy-paste in every Aggregate class.\r
+ //\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for Avg (column_Name)\r
+ /// </summary\r
+ internal class ExpressionAvg : ExpressionAggregate\r
+ {\r
+ public ExpressionAvg (string exp1)\r
+ {\r
+ ParseParameters (exp1);\r
+ }\r
+\r
+ public override object Result(DataRow[] rows)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ object value1 = E1.Result (rows[0]);\r
+ Type original = value1.GetType ();\r
+ object result = null;\r
+ \r
+ if (E1 is ExpressionSingleElement) \r
+ {\r
+ \r
+ Type t1 = null;\r
+ // This should be optimized somehow\r
+ for (int i = 0; i < rows.Length; i++) \r
+ {\r
+ \r
+ // TODO: other types and exceptions\r
+ object v = E1.Result (rows[i]);\r
+\r
+ if (v == null || v == DBNull.Value)\r
+ continue;\r
+\r
+ t1 = v.GetType ();\r
+\r
+ if (result == null)\r
+ result = 0;\r
+ \r
+ if (t1 == typeof (long)) \r
+ {\r
+ result = (long)result + (long)v;\r
+ }\r
+ else if (t1 == typeof (int)) \r
+ {\r
+ result = (int)result + (int)v;\r
+ }\r
+ else if (t1 == typeof (short)) \r
+ {\r
+ result = (short)result + (short)v;\r
+ }\r
+ else if (t1 == typeof (double)) \r
+ {\r
+ result = (double)result + (double)v;\r
+ }\r
+ else if (t1 == typeof (float)) \r
+ {\r
+ result = (float)result + (float)v;\r
+ }\r
+ else\r
+ throw new NotImplementedException ();\r
+ }\r
+\r
+ // TODO: types\r
+\r
+ if (t1 == typeof (long))\r
+ result = (long)result / rows.Length;\r
+ else if (t1 == typeof (int))\r
+ result = (int)result / rows.Length;\r
+ else if (t1 == typeof (short))\r
+ result = (short)result / rows.Length;\r
+ else if (t1 == typeof (double))\r
+ result = (double)result / rows.Length;\r
+ }\r
+ \r
+ return result;\r
+ }\r
+\r
+ /// <summary>\r
+ /// This is used from ExpressionStdDev for evaluating avg.\r
+ /// </summary>\r
+ public ExpressionAvg (ExpressionElement E)\r
+ {\r
+ Elements.Add (E);\r
+ }\r
+ \r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for Min (column_Name)\r
+ /// </summary\r
+ internal class ExpressionMin : ExpressionAggregate\r
+ {\r
+ public ExpressionMin (string exp1)\r
+ {\r
+ ParseParameters (exp1);\r
+ }\r
+\r
+ public override object Result(DataRow[] rows)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ object value1 = E1.Result (rows[0]);\r
+ Type original = value1.GetType ();\r
+ object result = null;\r
+ \r
+ if (E1 is ExpressionSingleElement) \r
+ {\r
+ \r
+ Type t1 = null;\r
+ // This should be optimized somehow\r
+ for (int i = 0; i < rows.Length; i++)\r
+ {\r
+ \r
+ // TODO: other types and exceptions\r
+ object v = E1.Result (rows[i]);\r
+\r
+ if (v == null || v == DBNull.Value)\r
+ continue;\r
+\r
+ t1 = v.GetType ();\r
+\r
+ if (result == null)\r
+ result = 0;\r
+\r
+ object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
+ BindingFlags.InvokeMethod, null, \r
+ v, \r
+ new object [] {result});\r
+\r
+ if ((int)CompResult < 0)\r
+ result = v;\r
+\r
+ }\r
+ }\r
+ \r
+ return result;\r
+ }\r
+\r
+ \r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for Max (column_Name)\r
+ /// </summary\r
+ internal class ExpressionMax : ExpressionAggregate\r
+ {\r
+ public ExpressionMax (string exp1)\r
+ {\r
+ ParseParameters (exp1);\r
+ }\r
+\r
+ public override object Result(DataRow[] rows)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ object value1 = E1.Result (rows[0]);\r
+ Type original = value1.GetType ();\r
+ object result = null;\r
+ \r
+ if (E1 is ExpressionSingleElement) \r
+ {\r
+ \r
+ Type t1 = null;\r
+ // This should be optimized somehow\r
+ for (int i = 0; i < rows.Length; i++) \r
+ {\r
+ \r
+ // TODO: other types and exceptions\r
+ object v = E1.Result (rows[i]);\r
+\r
+ if (v == null || v == DBNull.Value)\r
+ continue;\r
+\r
+ t1 = v.GetType ();\r
+\r
+ if (result == null)\r
+ result = 0;\r
+\r
+ object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
+ BindingFlags.InvokeMethod, null, \r
+ v, \r
+ new object [] {result});\r
+\r
+ if ((int)CompResult > 0)\r
+ result = v;\r
+\r
+ }\r
+ }\r
+ \r
+ return result;\r
+ }\r
+\r
+ \r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Class for count (column)\r
+ /// </summary>\r
+ internal class ExpressionCount : ExpressionAggregate\r
+ {\r
+ public ExpressionCount (string exp1)\r
+ {\r
+ ParseParameters (exp1);\r
+ }\r
+ \r
+ public override object Result(DataRow[] rows)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ int count = 0;\r
+\r
+ if (E1 is ExpressionSingleElement) \r
+ count = rows.Length;\r
+ \r
+ return count;\r
+ }\r
+\r
+ public override object Result (DataRow Row) \r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ int count = 0;\r
+\r
+ if (E1 is ExpressionSingleElement) \r
+ {\r
+ \r
+ count = Row.Table.Rows.Count;\r
+ }\r
+ \r
+ return count;\r
+ }\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Class for StdDev (column)\r
+ /// </summary>\r
+ internal class ExpressionStdev : ExpressionAggregate\r
+ {\r
+ public ExpressionStdev (string exp1)\r
+ { \r
+ ParseParameters (exp1);\r
+ }\r
+\r
+ public override object Result(DataRow[] rows)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionAvg Avg = new ExpressionAvg (E1);\r
+\r
+ object tempAvg = Avg.Result (rows[0]);\r
+ double avg = 0;\r
+ double sum = 0;\r
+ double result = 0;\r
+\r
+ if (tempAvg.GetType () == typeof (int))\r
+ avg = (double)(int)tempAvg;\r
+ \r
+ if (E1 is ExpressionSingleElement) \r
+ {\r
+\r
+ for (int i = 0; i <rows.Length; i++)\r
+ {\r
+ // (value - avg)²\r
+ object v = E1.Result (rows[i]);\r
+\r
+ if (v == null || v == DBNull.Value)\r
+ continue;\r
+\r
+ if (v.GetType () == typeof (long))\r
+ sum = avg - (long)v;\r
+ else if (v.GetType () == typeof (int))\r
+ sum = avg - (int)v;\r
+ else if (v.GetType () == typeof (short))\r
+ sum = avg - (short)v;\r
+ else\r
+ throw new NotImplementedException ();\r
+\r
+ result += Math.Pow (sum, 2);\r
+ }\r
+ \r
+ result = result / (rows.Length - 1);\r
+ result = Math.Sqrt (result);\r
+ }\r
+\r
+ return result;\r
+ }\r
+ \r
+ \r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for Var (column)\r
+ /// </summary>\r
+ internal class ExpressionVar : ExpressionAggregate\r
+ {\r
+ public ExpressionVar (string exp1)\r
+ {\r
+ ParseParameters (exp1);\r
+ }\r
+\r
+ public override object Result(DataRow[] rows)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionAvg Avg = new ExpressionAvg (E1);\r
+\r
+ object tempAvg = Avg.Result (rows[0]);\r
+ double avg = 0;\r
+ double sum = 0;\r
+ double result = 0;\r
+\r
+ if (tempAvg.GetType () == typeof (int))\r
+ avg = (double)(int)tempAvg;\r
+ \r
+ if (E1 is ExpressionSingleElement) \r
+ {\r
+\r
+ for (int i = 0; i < rows.Length; i++)\r
+ {\r
+\r
+ \r
+ // (value - avg)²\r
+ object v = E1.Result (rows[i]);\r
+\r
+ if (v == null || v == DBNull.Value)\r
+ continue;\r
+\r
+ if (v.GetType () == typeof (long))\r
+ sum = avg - (long)v;\r
+ else if (v.GetType () == typeof (int))\r
+ sum = avg - (int)v;\r
+ else if (v.GetType () == typeof (short))\r
+ sum = avg - (short)v;\r
+ else\r
+ throw new NotImplementedException ();\r
+\r
+ result += Math.Pow (sum, 2);\r
+ }\r
+ \r
+ result = result / (rows.Length - 1);\r
+ }\r
+\r
+ return result;\r
+ }\r
+ \r
+ \r
+ }\r
+\r
+ // \r
+ // _____F_U_ N_C_T_I_O_N_S_______\r
+ //\r
+\r
+ /// <summary>\r
+ /// Class for len (string) function\r
+ /// </summary>\r
+ internal class ExpressionLen : ExpressionElement\r
+ {\r
+ public ExpressionLen (string exp1)\r
+ { \r
+ _ResultType = typeof (int);\r
+ ParseParameters (exp1);\r
+ }\r
+ \r
+ public override object Result (DataRow Row) \r
+ {\r
+ ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+ object value1 = E1.Result (Row);\r
+ \r
+ return value1.ToString ().Length;\r
+ }\r
+ \r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ public void ParseParameters (string s)\r
+ {\r
+ string stemp = s.ToLower ();\r
+ bool inString = false;\r
+ string p1 = null;\r
+\r
+ // find (\r
+ while (!s.StartsWith ("("))\r
+ s = s.Remove (0, 1);\r
+\r
+ // remove (\r
+ s = s.Remove (0, 1);\r
+ int parentheses = 0;\r
+ for (int i = 0; i < s.Length; i++) \r
+ {\r
+\r
+ if (s [i] == '\'')\r
+ inString = !inString;\r
+ else if (s [i] == '(')\r
+ parentheses++;\r
+ else if (s [i] == ')')\r
+ parentheses--;\r
+\r
+ if ((s [i] == ',' || s [i] == ')') && !inString && parentheses == -1) \r
+ { // Parameter changed\r
+\r
+ if (p1 == null) \r
+ {\r
+ p1 = s.Substring (0, i);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (p1 == null)\r
+ throw new Exception ();\r
+\r
+ ParseExpression (p1); \r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for iif (exp1, truepart, falsepart) function\r
+ /// </summary>\r
+ internal class ExpressionIif : ExpressionElement\r
+ {\r
+ public ExpressionIif (string exp)\r
+ { \r
+ ParseParameters (exp);\r
+ }\r
+\r
+ public override object Result (DataRow Row) \r
+ {\r
+ ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+ ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+ ExpressionElement E3 = ((ExpressionElement)Elements [2]);\r
+\r
+ if (E1.Test (Row)) // expression\r
+ return E2.Result (Row); // truepart\r
+ else\r
+ return E3.Result (Row); // false part \r
+ }\r
+ \r
+ // This method is shouldnt never invoked\r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ public override Type ResultType (DataRow Row)\r
+ { \r
+ ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+ ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+ ExpressionElement E3 = ((ExpressionElement)Elements [2]);\r
+ \r
+ if (E1.Test (Row)) // expression\r
+ return E2.Result (Row).GetType (); // truepart\r
+ else\r
+ return E3.Result (Row).GetType (); // false part \r
+ }\r
+\r
+ /// <summary>\r
+ /// Parses expressions in parameters (exp, truepart, falsepart)\r
+ /// </summary>\r
+ private void ParseParameters (string s)\r
+ {\r
+ bool inString = false;\r
+ string stemp = s.ToLower ();\r
+ string p1 = null;\r
+ string p2 = null;\r
+ string p3 = null;\r
+ s = s.Substring (stemp.IndexOf ("iif") + 3);\r
+\r
+ // find (\r
+ while (!s.StartsWith ("("))\r
+ s = s.Remove (0, 1);\r
+\r
+ // remove (\r
+ s = s.Remove (0, 1);\r
+ int parentheses = 0;\r
+ for (int i = 0; i < s.Length; i++) \r
+ {\r
+\r
+ if (s [i] == '\'')\r
+ inString = !inString;\r
+ else if (s [i] == '(')\r
+ parentheses++;\r
+ else if (s [i] == ')')\r
+ parentheses--;\r
+\r
+ if ((s [i] == ',' && !inString && parentheses == 0) || \r
+ (s [i] == ')' && i == (s.Length -1))) \r
+ { // Parameter changed\r
+\r
+ if (p1 == null) \r
+ {\r
+ p1 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else if (p2 == null) \r
+ {\r
+ p2 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else if (p3 == null) \r
+ {\r
+ p3 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else\r
+ throw new Exception (); // FIXME: What exception\r
+ }\r
+ }\r
+\r
+ if (p1 == null || p2 == null || p3 == null)\r
+ throw new Exception ();\r
+\r
+ ParseExpression (p1);\r
+ ParseExpression (p2);\r
+ ParseExpression (p3);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for isnull (expression, returnvalue) function\r
+ /// </summary>\r
+ internal class ExpressionIsNull : ExpressionElement\r
+ {\r
+ public ExpressionIsNull (string exp)\r
+ { \r
+ ParseParameters (exp);\r
+ }\r
+ \r
+ public override object Result (DataRow Row) \r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+ \r
+ object R1 = E1.Result (Row);\r
+ object value1 = null;\r
+ if (R1 == null || R1 == DBNull.Value)\r
+ return E2.Result (Row);\r
+ else\r
+ return R1;\r
+ }\r
+\r
+ public override Type ResultType (DataRow Row)\r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+ \r
+ object R1 = E1.Result (Row);\r
+ object value1 = null;\r
+ if (R1 == null || R1 == DBNull.Value)\r
+ return E2.Result (Row).GetType ();\r
+ else\r
+ return R1.GetType ();\r
+ }\r
+ \r
+ /// <summary>\r
+ /// IsNull function does not return boolean value, so throw exception\r
+ /// </summary>\r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Parses parameters of function and invoke ParseExpression methods\r
+ /// </summary>\r
+ private void ParseParameters (string s)\r
+ {\r
+ bool inString = false;\r
+ string stemp = s.ToLower ();\r
+ string p1 = null;\r
+ string p2 = null;\r
+\r
+ s = s.Substring (stemp.IndexOf ("isnull") + 6);\r
+\r
+ // find (\r
+ while (!s.StartsWith ("("))\r
+ s = s.Remove (0, 1);\r
+\r
+ // remove (\r
+ s = s.Remove (0, 1);\r
+ int parentheses = 0;\r
+ for (int i = 0; i < s.Length; i++) \r
+ {\r
+\r
+ if (s [i] == '\'')\r
+ inString = !inString;\r
+ else if (s [i] == '(')\r
+ parentheses++;\r
+ else if (s [i] == ')')\r
+ parentheses--;\r
+\r
+ if ((s [i] == ',' && !inString && parentheses == 0) || \r
+ (s [i] == ')' && i == (s.Length -1))) \r
+ { // Parameter changed\r
+\r
+ if (p1 == null) \r
+ {\r
+ p1 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else if (p2 == null) \r
+ {\r
+ p2 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else\r
+ throw new Exception (); // FIXME: What exception\r
+ }\r
+ }\r
+\r
+ if (p1 == null || p2 == null)\r
+ throw new Exception ();\r
+\r
+ ParseExpression (p1);\r
+ ParseExpression (p2);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for Substring (expression, start, length) function\r
+ /// </summary>\r
+ internal class ExpressionSubstring : ExpressionElement\r
+ {\r
+ public ExpressionSubstring (string exp)\r
+ { \r
+ ParseParameters (exp);\r
+ _ResultType = typeof (string);\r
+ }\r
+ \r
+ public override object Result (DataRow Row) \r
+ {\r
+ ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+ ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+ ExpressionElement E3 = (ExpressionElement)Elements [2];\r
+ \r
+ object value1 = E1.Result (Row);\r
+ object value2 = E2.Result (Row);\r
+ object value3 = E3.Result (Row);\r
+ Type t1 = value1.GetType ();\r
+ Type t2 = value2.GetType ();\r
+ Type t3 = value3.GetType ();\r
+\r
+ if (value1 == null || value2 == null || value3 == null \r
+ || value1 == DBNull.Value || value2 == DBNull.Value || value3 == DBNull.Value)\r
+ return string.Empty;\r
+\r
+ if (t1 != typeof (string))\r
+ throw new Exception (); // FIXME: what exception\r
+ else if (t2 != typeof (int))\r
+ throw new EvaluateException ("Type mismatch is function argument: Substring (), argument 2, excepted System.Int32");\r
+ else if (t3 != typeof (int))\r
+ throw new EvaluateException ("Type mismatch is function argument: Substring (), argument 3, excepted System.Int32");\r
+\r
+ string str = value1.ToString ();\r
+ int start = (int)value2;\r
+ int length = (int)value3;\r
+\r
+ if (str.Length < start)\r
+ str = string.Empty;\r
+ else \r
+ {\r
+ if ((start + length - 1) > str.Length)\r
+ str = str.Substring (start - 1);\r
+ else\r
+ str = str.Substring (start - 1, length);\r
+ }\r
+\r
+ return str;\r
+ }\r
+\r
+ /// <summary>\r
+ /// IsNull function does not return boolean value, so throw exception\r
+ /// </summary>\r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Parses parameters of function and invoke ParseExpression methods\r
+ /// </summary>\r
+ private void ParseParameters (string s)\r
+ {\r
+ bool inString = false;\r
+ string stemp = s.ToLower ();\r
+ string p1 = null;\r
+ string p2 = null;\r
+ string p3 = null;\r
+\r
+ s = s.Substring (stemp.IndexOf ("substring") + 9);\r
+\r
+ // find (\r
+ while (!s.StartsWith ("("))\r
+ s = s.Remove (0, 1);\r
+\r
+ // remove (\r
+ s = s.Remove (0, 1);\r
+ int parentheses = 0;\r
+ for (int i = 0; i < s.Length; i++) \r
+ {\r
+\r
+ if (s [i] == '\'')\r
+ inString = !inString;\r
+ else if (s [i] == '(')\r
+ parentheses++;\r
+ else if (s [i] == ')')\r
+ parentheses--;\r
+\r
+\r
+ if ((s [i] == ',' && !inString && parentheses == 0) || \r
+ (s [i] == ')' && i == (s.Length -1))) \r
+ { // Parameter changed\r
+\r
+ if (p1 == null) \r
+ {\r
+ p1 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else if (p2 == null) \r
+ {\r
+ p2 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else if (p3 == null) \r
+ {\r
+ p3 = s.Substring (0, i);\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+\r
+ else\r
+ throw new Exception (); // FIXME: What exception\r
+ }\r
+ }\r
+\r
+ if (p1 == null || p2 == null)\r
+ throw new Exception ();\r
+\r
+ ParseExpression (p1);\r
+ ParseExpression (p2);\r
+ ParseExpression (p3); \r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for In (exp, exp, exp, ...) function\r
+ /// </summary>\r
+ internal class ExpressionIn : ExpressionElement\r
+ {\r
+ public ExpressionIn (string exp1, string exp2)\r
+ { \r
+ ParseExpression(exp1);\r
+ ParseParameters (exp2);\r
+ }\r
+\r
+ /// <summary>\r
+ /// IsNull function does not return boolean value, so throw exception\r
+ /// </summary>\r
+ public override bool Test (DataRow Row) \r
+ {\r
+ ExpressionElement E;\r
+ ExpressionElement columnElement = (ExpressionElement)Elements [0];\r
+\r
+ ExpressionElementComparer comparer = new ExpressionElementComparer(columnElement, Row);\r
+\r
+ for (int i = 1; i < Elements.Count; i++)\r
+ {\r
+ E = (ExpressionElement)Elements [i];\r
+ if(comparer.CompareTo(E) == 0)\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Parses parameters of function and invoke ParseExpression methods\r
+ /// </summary>\r
+ private void ParseParameters (string s)\r
+ {\r
+ bool inString = false;\r
+ ArrayList parameters = new ArrayList();\r
+ \r
+ // find (\r
+ while (!s.StartsWith ("("))\r
+ s = s.Remove (0, 1);\r
+\r
+ // remove (\r
+ s = s.Remove (0, 1);\r
+ int parentheses = 0;\r
+ for (int i = 0; i < s.Length; i++) \r
+ {\r
+\r
+ if (s [i] == '\'')\r
+ inString = !inString;\r
+ else if (s [i] == '(')\r
+ parentheses++;\r
+ else if (s [i] == ')')\r
+ parentheses--;\r
+\r
+\r
+ if ((s [i] == ',' && !inString && parentheses == 0) || \r
+ (s [i] == ')' && i == (s.Length -1))) \r
+ {\r
+ parameters.Add(s.Substring (0, i));\r
+ s = s.Substring (i + 1);\r
+ i = 0;\r
+ }\r
+ }\r
+ \r
+ for (int i = 0; i < parameters.Count; i++)\r
+ ParseExpression((string)parameters[i]);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Class for just one element for example string, int, ...\r
+ /// </summary>\r
+ internal class ExpressionSingleElement : ExpressionElement\r
+ { \r
+ private object Element = null;\r
+ \r
+ public ExpressionSingleElement (string s)\r
+ {\r
+ // TODO: Every type should be checked\r
+ if (s.StartsWith ("'") && s.EndsWith ("'")) \r
+ {\r
+ Element = s.Substring (1, s.Length - 2);\r
+ _ResultType = typeof (string);\r
+ }\r
+ else if (!Char.IsDigit (s [0]) && s [0] != '-' && s [0] != '+') \r
+ {\r
+ Element = s;\r
+ _ResultType = typeof (DataColumn);\r
+ }\r
+ else if (s.StartsWith ("#") && s.EndsWith ("#")) \r
+ {\r
+ Element = DateTime.Parse (s.Substring (1, s.Length - 2));\r
+ _ResultType = typeof (DateTime);\r
+ }\r
+ else \r
+ {\r
+ try \r
+ {\r
+ Element = int.Parse (s);\r
+ _ResultType = typeof (int);\r
+ } \r
+ catch \r
+ {\r
+ Element = Decimal.Parse (s);\r
+ _ResultType = typeof (Decimal);\r
+ }\r
+ } \r
+ }\r
+\r
+ public override object Result (DataRow Row)\r
+ {\r
+ object Result = null;\r
+ if (ResultType (Row) == typeof (DataColumn)) \r
+ {\r
+ \r
+ if (!Row.Table.Columns.Contains (Element.ToString ()))\r
+ throw new EvaluateException ("Column name '" + Element.ToString () + "' not found.");\r
+ else\r
+ {\r
+ DataRowVersion rowVersion = DataRowVersion.Default;\r
+ // if this row is deleted we get the original version, or else we get an exception.\r
+ if (Row.RowState == DataRowState.Deleted)\r
+ rowVersion = DataRowVersion.Original;\r
+ Result = Row [Element.ToString (), rowVersion];\r
+ }\r
+ }\r
+ else\r
+ Result = Element;\r
+ \r
+ return Result;\r
+ }\r
+ \r
+ public override bool Test (DataRow Row)\r
+ {\r
+ throw new EvaluateException ();\r
+ } \r
+ }\r
+\r
+ /// <summary>\r
+ /// Parent class of all the elements of expression\r
+ /// </summary>\r
+ internal abstract class ExpressionElement\r
+ { \r
+ enum OP {OPERATOR, OPERAND};\r
+ enum OPERATOR_TYPE {SYMBOLIC, LITERAL, UNDEFINED};\r
+ enum OPERAND_TYPE {NUMERIC, STRING, UNDEFINED};\r
+\r
+ // \r
+ // TODO/FIXME: This class should be inherited more than once. I mean own subclass for operators, functions,...\r
+ //\r
+\r
+ protected string exp1;\r
+ protected string exp2;\r
+ protected Type _ResultType;\r
+\r
+ protected ArrayList Elements = new ArrayList ();\r
+\r
+ enum AGGREGATE {SUM, AVG, MIN, MAX, COUNT, STDEV, VAR}\r
+ //protected ArrayList Singles = new ArrayList ();\r
+ \r
+ /// <summary>\r
+ /// Tells does the current expressions match to current DataRow\r
+ /// </summary>\r
+ abstract public bool Test (DataRow Row);\r
+\r
+ public virtual object Result (DataRow Row) {return null;}\r
+ \r
+ public virtual Type ResultType (DataRow Row)\r
+ {\r
+ return _ResultType;\r
+ }\r
+\r
+ protected object CalculateResult (DataRow Row)\r
+ {\r
+ ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+ ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+ object Result = null;\r
+ object value1 = E1.Result (Row);\r
+ object value2 = E2.Result (Row);\r
+ Type t1 = value1.GetType ();\r
+ Type t2 = value2.GetType ();\r
+ \r
+ // Check nulls\r
+ if (value1 == DBNull.Value && value2 == DBNull.Value)\r
+ return null;\r
+ \r
+ // TODO: More types\r
+ \r
+ if (t1 == typeof (string) || t2 == typeof (string)) \r
+ {\r
+ \r
+ if (t1 != typeof (string))\r
+ value1 = Convert.ChangeType (value1, Type.GetTypeCode (t2));\r
+ else if (t2 != typeof (string))\r
+ value2 = Convert.ChangeType (value2, Type.GetTypeCode (t1));\r
+ }\r
+ \r
+ if (t1 != t2)\r
+ value2 = Convert.ChangeType (value2, Type.GetTypeCode (t1));\r
+ \r
+ Result = Calculate (value1, value2, t1);\r
+ \r
+ return Result; \r
+ }\r
+ protected virtual object Calculate (object value1, object value2, Type TempType)\r
+ {\r
+ return null;\r
+ }\r
+ \r
+ /// <summary>\r
+ /// static method for comparing two ExpressionElement. This is used in =, <, >, <>, <=, >= elements.\r
+ /// If elements are equal returns 0, if E1 is less that E2, return -1 else if E1 is greater 1 \r
+ /// </summary>\r
+ protected static int Compare (ExpressionElement E1, ExpressionElement E2, DataRow Row)\r
+ { \r
+ ExpressionElementComparer comparer = new ExpressionElementComparer(E1, Row);\r
+\r
+ return comparer.CompareTo(E2);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Checks syntax of expression and throws exception if needed.\r
+ /// Also removes whitespaces between operator elements for example: age < = 64 --> age <= 64\r
+ /// </summary>\r
+ internal static string ValidateExpression (string s)\r
+ { \r
+ //\r
+ // TODO: find out nice way to do this. This is NOT nice way :-P\r
+ //\r
+ //string temp = "";\r
+ OP op = OP.OPERAND;\r
+ OPERATOR_TYPE operatorType = OPERATOR_TYPE.UNDEFINED;\r
+\r
+ StringBuilder strOperator = new StringBuilder();\r
+ StringBuilder strOperand = new StringBuilder();\r
+ int quotes = 0;\r
+ int parentheses = 0;\r
+ StringBuilder newExp = new StringBuilder();\r
+ bool isDigit = false;\r
+ //bool litOperator = false;\r
+ s = s.Trim();\r
+ \r
+ for (int i = 0; i < s.Length; i++) \r
+ {\r
+\r
+ char c = s [i];\r
+ \r
+ if (c == '\'')\r
+ quotes++;\r
+\r
+ if ((c == '\n' || c == '\t') && quotes == 0)\r
+ c = ' ';\r
+\r
+ if (op == OP.OPERAND && c == '(')\r
+ parentheses++;\r
+ else if (op == OP.OPERAND && c == ')')\r
+ parentheses--;\r
+\r
+ if (c == ' ' && op == OP.OPERAND && (quotes % 2) == 0 && parentheses == 0) \r
+ {\r
+ \r
+ op = OP.OPERATOR;\r
+ int max = strOperand.Length;\r
+ for (int it = 0; it < max; it++)\r
+ newExp.Append(strOperand[it]);\r
+ strOperand.Remove(0, max);\r
+ strOperator.Append(' ');\r
+ }\r
+\r
+ if (op == OP.OPERAND) \r
+ {\r
+\r
+ if (!Char.IsDigit (c) && isDigit && (quotes % 2) == 0) \r
+ {\r
+ int max = strOperand.Length;\r
+ for (int it = 0; it < max; it++)\r
+ newExp.Append(strOperand[it]);\r
+ strOperand.Remove(0, max);\r
+ op = OP.OPERATOR;\r
+ operatorType = OPERATOR_TYPE.UNDEFINED;\r
+ }\r
+ else\r
+ strOperand.Append(c);\r
+ }\r
+\r
+ if (op == OP.OPERATOR) \r
+ {\r
+\r
+ isDigit = false;\r
+ if (operatorType == OPERATOR_TYPE.UNDEFINED) \r
+ {\r
+\r
+ if (c == '<' || c == '=' || c == '>' || c == '*' || c == '/' || c == '%' \r
+ || c == '-' || c == '+')\r
+\r
+ operatorType = OPERATOR_TYPE.SYMBOLIC;\r
+ else if (c != ' ')\r
+ operatorType = OPERATOR_TYPE.LITERAL;\r
+ }\r
+ else if (operatorType == OPERATOR_TYPE.SYMBOLIC) \r
+ {\r
+ \r
+ //Checking for operators following one another\r
+ if ((c == '=' || c== '<' || c== '>') &&\r
+ (strOperator.Length == 2) &&\r
+ (strOperator[0] == ' '))\r
+ {\r
+ char chSecond = strOperator[1];\r
+ if (chSecond == '+' ||\r
+ chSecond == '-' ||\r
+ chSecond == '%' ||\r
+ chSecond == '*')\r
+ throw new SyntaxErrorException (\r
+ "The operator " + strOperator.ToString() + c + " is not valid");\r
+ }\r
+\r
+ // this is COPY-PASTE\r
+ op = OP.OPERAND;\r
+ if (newExp[newExp.Length - 1] != ' ' && \r
+ strOperator[0] != ' ')\r
+ newExp.Append(' ');\r
+\r
+ int max = strOperator.Length;\r
+ for (int it = 0; it < max; it++)\r
+ newExp.Append(strOperator[it]);\r
+ strOperator.Remove(0, max);\r
+\r
+ if (Char.IsDigit (c))\r
+ isDigit = true;\r
+ \r
+ strOperand.Remove(0, strOperand.Length);\r
+ strOperand.Append(c);\r
+ \r
+ continue;\r
+\r
+ }\r
+\r
+ if (operatorType == OPERATOR_TYPE.LITERAL && c == ' ') \r
+ {\r
+ op = OP.OPERAND;\r
+ int max = strOperator.Length;\r
+ for (int it = 0; it < max; it++)\r
+ newExp.Append(strOperator[it]);\r
+ strOperator.Remove(0, max);\r
+\r
+ strOperand.Append(' ');\r
+ }\r
+\r
+\r
+ if (Char.IsDigit (c) && operatorType != OPERATOR_TYPE.LITERAL) \r
+ {\r
+\r
+ op = OP.OPERAND;\r
+ if (newExp[newExp.Length - 1] != ' ' && \r
+ strOperator[0] != ' ')\r
+ newExp.Append(' ');\r
+\r
+ int max = strOperator.Length;\r
+ for (int it = 0; it < max; it++)\r
+ newExp.Append(strOperator[it]);\r
+ strOperator.Remove(0, max);\r
+\r
+ if (Char.IsDigit (c))\r
+ isDigit = true;\r
+ \r
+ strOperand.Remove(0, strOperand.Length);\r
+ strOperand.Append(c);\r
+ }\r
+\r
+ else if (c != ' ')\r
+ strOperator.Append(c); \r
+ }\r
+ }\r
+\r
+ if (op == OP.OPERATOR)\r
+ throw new SyntaxErrorException (\r
+ "Missing operand after '" + strOperator.ToString() + "' operator");\r
+ else\r
+ {\r
+ int max = strOperand.Length;\r
+ for (int it = 0; it < max; it++)\r
+ newExp.Append(strOperand[it]);\r
+ }\r
+\r
+ return newExp.ToString();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Finds and creates Expression elements.\r
+ /// This presumes that expression is valid.\r
+ /// </summary>\r
+ protected void ParseExpression (string s)\r
+ { \r
+ //\r
+ // TODO/FIXME: IMHO, this should be done with different kind of parsing:\r
+ // char by char not operand by operand. \r
+ // fixed the easy places, should consider better parsing\r
+ //\r
+\r
+ string inside = String.Empty; // stores string betwee parentheses like a = 12 and (b = 1 or b = 2)\r
+ string lower = s.ToLower();\r
+ //string function = ""; // stores fuction paramters like substring (this, are, paramters)\r
+ //string s1 = "";\r
+ //string s2 = "";\r
+ int startIndex = lower.IndexOf ('(');\r
+ \r
+ // Find parenthesis\r
+ if (startIndex != -1) \r
+ {\r
+ string functionName = String.Empty;\r
+ if (startIndex > 0)\r
+ {\r
+ int functionStart = lower.LastIndexOf('=', startIndex-1, startIndex);\r
+ if (functionStart < 0)\r
+ functionStart++;\r
+ functionName = lower.Substring(functionStart, startIndex);\r
+\r
+ functionName = functionName.Trim ();\r
+ }\r
+\r
+ // check if previous element is a function\r
+ if (functionName.Length == 0 || (!functionName.EndsWith ("convert") && !functionName.EndsWith ("len") &&\r
+ !functionName.EndsWith ("isnull") && !functionName.EndsWith ("iif") &&\r
+ !functionName.EndsWith ("trim") && !functionName.EndsWith ("substring") &&\r
+ !functionName.EndsWith ("sum") && !functionName.EndsWith ("avg") &&\r
+ !functionName.EndsWith ("min") && !functionName.EndsWith ("max") &&\r
+ !functionName.EndsWith ("count") && !functionName.EndsWith ("stdev") &&\r
+ !functionName.EndsWith ("var")&& !functionName.EndsWith ("in"))) \r
+ {\r
+ \r
+ \r
+ int i = startIndex + 1;\r
+ int max = lower.Length;\r
+ \r
+ for (int par = 1; par > 0 && i < max; i++) \r
+ {\r
+\r
+ char c = s [i];\r
+ if (c == '(')\r
+ par++;\r
+ else\r
+ if (c == ')')\r
+ par--;\r
+ }\r
+ \r
+ inside = s.Substring(startIndex + 1, i - startIndex - 2); \r
+ lower = lower.Remove (startIndex, i - startIndex);\r
+ s = s.Remove (startIndex, i - startIndex);\r
+ } \r
+ \r
+ }\r
+ \r
+ string string1 = null;\r
+ string string2 = null;\r
+ if (FindOrElement (s, lower, ref string1, ref string2)) \r
+ CreateOrElement (string1, string2, inside);\r
+\r
+ else if (FindAndElement (s, lower, ref string1, ref string2))\r
+ CreateAndElement (string1, string2, inside);\r
+\r
+ // find LIKE\r
+ else if (FindLikeElement (s, lower, ref string1, ref string2))\r
+ CreateLikeElement (string1, string2, inside);\r
+ \r
+ // find IN\r
+ else if (FindInElement (s, lower, ref string1, ref string2))\r
+ CreateInElement (string1, string2, inside);\r
+\r
+ // find =\r
+ else if (FindEqualElement (s, lower, ref string1, ref string2))\r
+ CreateEqualsElement (string1, string2, inside);\r
+\r
+ // find <>\r
+ else if (FindUnequalElement (s, lower, ref string1, ref string2))\r
+ CreateUnequalsElement (string1, string2, inside);\r
+\r
+ // find <=\r
+ else if (FindLessThanOrEqualElement (s, lower, ref string1, ref string2))\r
+ CreateLessThanOrEqualElement (string1, string2, inside);\r
+\r
+ // find <\r
+ else if (FindLessThanElement (s, lower, ref string1, ref string2))\r
+ CreateLessThanElement (string1, string2, inside);\r
+\r
+ // find >=\r
+ else if (FindGreaterThanOrEqualElement (s, lower, ref string1, ref string2))\r
+ CreateGreaterThanOrEqualElement (string1, string2, inside);\r
+\r
+ // find >\r
+ else if (FindGreaterThanElement (s, lower, ref string1, ref string2))\r
+ CreateGreaterThanElement (string1, string2, inside);\r
+\r
+ // if there wasn't any operators like 'and' or 'not' there still could be\r
+ // arithmetic operators like '+' or '-' or functions like 'iif' or 'substring'\r
+\r
+ // find *\r
+ else if (FindMultiplyElement (s, lower, ref string1, ref string2))\r
+ CreateMultiplyElement (string1, string2, inside);\r
+ \r
+ // find /\r
+ else if (FindDivideElement (s, lower, ref string1, ref string2))\r
+ CreateDivideElement (string1, string2, inside);\r
+\r
+\r
+ // find +\r
+ else if (FindAdditionElement (s, lower, ref string1, ref string2))\r
+ CreateAdditionElement (string1, string2, inside);\r
+\r
+ // find -\r
+ else if (FindSubtractElement (s, lower, ref string1, ref string2))\r
+ CreateSubtractionElement (string1, string2, inside);\r
+\r
+ // find %\r
+ else if (FindModulusElement (s, lower, ref string1, ref string2))\r
+ CreateModulusElement (string1, string2, inside);\r
+\r
+ // find sum ()\r
+ else if (FindAggregateElement (s, lower, AGGREGATE.SUM))\r
+ Elements.Add (new ExpressionSum (s.Trim ()));\r
+\r
+ // find avg ()\r
+ else if (FindAggregateElement (s, lower, AGGREGATE.AVG))\r
+ Elements.Add (new ExpressionAvg (s.Trim ()));\r
+\r
+ // find min ()\r
+ else if (FindAggregateElement (s, lower, AGGREGATE.MIN))\r
+ Elements.Add (new ExpressionMin (s.Trim ()));\r
+\r
+ // find max ()\r
+ else if (FindAggregateElement (s, lower, AGGREGATE.MAX))\r
+ Elements.Add (new ExpressionMax (s.Trim ()));\r
+\r
+ // find count ()\r
+ else if (FindAggregateElement (s, lower, AGGREGATE.COUNT))\r
+ Elements.Add (new ExpressionCount (s.Trim ())); \r
+\r
+ // find stdev ()\r
+ else if (FindAggregateElement (s, lower, AGGREGATE.STDEV))\r
+ Elements.Add (new ExpressionStdev (s.Trim ()));\r
+\r
+ // find var ()\r
+ else if (FindAggregateElement (s, lower, AGGREGATE.VAR))\r
+ Elements.Add (new ExpressionVar (s.Trim ()));\r
+\r
+ // find len\r
+ else if (FindLenElement (s, lower))\r
+ Elements.Add (new ExpressionLen (s.Trim ()));\r
+\r
+ // find iif\r
+ else if (FindIifElement (s, lower))\r
+ Elements.Add (new ExpressionIif (s.Trim ()));\r
+\r
+ // find isnull\r
+ else if (FindIsNullElement (s, lower))\r
+ Elements.Add (new ExpressionIsNull (s.Trim ()));\r
+\r
+ // find substring\r
+ else if (FindSubstringElement (s, lower))\r
+ Elements.Add (new ExpressionSubstring (s.Trim ()));\r
+\r
+ // if expression is like '(something someoperator something)'\r
+ else if (inside.Trim () != string.Empty)\r
+ ParseExpression (inside);\r
+\r
+ // At least, if it wasnt any of the above it is just normat string or int\r
+ // or.... \r
+ else\r
+ Elements.Add (new ExpressionSingleElement (s.Trim ())); \r
+ }\r
+\r
+ #region CheckElement methods\r
+\r
+ //\r
+ // These methods are temporary for now\r
+ //\r
+\r
+ private bool FindOrElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf("or");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ // Test if or is between ''\r
+ int oldIndex = -1; \r
+ while ((indexOf = stemp.IndexOf ("or", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+ \r
+ oldIndex = indexOf;\r
+\r
+ // check is the 'or' element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+ \r
+ // Check is or part of something else for example column name\r
+ if (indexOf != 0) \r
+ {\r
+ \r
+ if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+ continue;\r
+ }\r
+ \r
+ if (indexOf < s.Length + 2) \r
+ {\r
+ \r
+ if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')\r
+ continue;\r
+ }\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 2).Trim ();\r
+\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+ \r
+ private bool FindAndElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf("and");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ // Test if or is between ''\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("and", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+ \r
+ oldIndex = indexOf;\r
+ \r
+ // check is the 'and' element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ // Check is or part of something else for example column name\r
+ if (indexOf != 0) \r
+ {\r
+ \r
+ if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+ continue;\r
+ }\r
+ \r
+ if (indexOf < stemp.Length + 3) \r
+ {\r
+ \r
+ if (stemp [indexOf + 3] != ' ' && stemp [indexOf + 3] != '\'')\r
+ continue;\r
+ }\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 3).Trim ();\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ private bool FindLikeElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf("like");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ // Test if or is between ''\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("like", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+ \r
+ oldIndex = indexOf;\r
+ \r
+ // check is the 'and' element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ // Check is or part of something else for example column name\r
+ if (indexOf != 0) \r
+ {\r
+ \r
+ if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+ continue;\r
+ }\r
+ \r
+ if (indexOf < stemp.Length + 4) \r
+ {\r
+ \r
+ if (stemp [indexOf + 4] != ' ' && stemp [indexOf + 4] != '\'')\r
+ continue;\r
+ }\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 4).Trim ();\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ private bool FindEqualElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("=");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+ \r
+ int oldIndex = -1;\r
+\r
+ while ((indexOf = stemp.IndexOf ("=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+\r
+ // Check is the = part of <= or >=\r
+ if (stemp [indexOf - 1] == '<' || stemp [indexOf - 1] == '>')\r
+ continue;\r
+\r
+ // Check is the = element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+ \r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+ \r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ private bool FindUnequalElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("<>");\r
+\r
+ if (stemp.IndexOf ("<>") == -1)\r
+ return false;\r
+ \r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("<>", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+\r
+ // test if next charachter is something else than ' '\r
+ bool failed = false;\r
+\r
+ // Check is the <> element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+ \r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 2).Trim ();\r
+ \r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ \r
+ }\r
+\r
+\r
+ private bool FindLessThanElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("<");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("<", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+\r
+ // if < is part of <> or <=\r
+ if (stemp [indexOf + 1] == '>' || stemp [indexOf + 1] == '=')\r
+ continue;\r
+\r
+ // Test is < element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindLessThanOrEqualElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("<=");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("<=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ // Test is <= element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 2).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindGreaterThanElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf (">");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf (">", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+\r
+ // if < is part of <> or <=\r
+ if (stemp [indexOf - 1] == '<' || stemp [indexOf + 1] == '=')\r
+ continue;\r
+\r
+ // Test is < element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindGreaterThanOrEqualElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf (">=");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf (">=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+ // Test is <= element part of string element\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 2).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindAdditionElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("+");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("+", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ // FIXME: if '+' represents sign of integer\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindSubtractElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("-");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("-", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // check is this lonely element \r
+ failed = true;\r
+ for (int i = indexOf - 1; i >= 0; i--) \r
+ {\r
+ if (stemp [i] != ' ') \r
+ {\r
+ failed = false;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if (failed)\r
+ continue;\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindMultiplyElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("*");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("*", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // FIXME: If there is a divide operator before multiply operator.\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindDivideElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("/");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("/", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // FIXME: If there is a multiply operator before divide operator.\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+ \r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindModulusElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("%");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("%", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // FIXME: If there is a multiply operator before divide operator.\r
+\r
+ // Check is or part of column name\r
+ if (IsPartOfColumnName (stemp, indexOf))\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindAggregateElement (string s, string lower, AGGREGATE aggregate)\r
+ {\r
+ string agg = null;\r
+\r
+ switch (aggregate) \r
+ {\r
+\r
+ case AGGREGATE.SUM:\r
+ agg = "sum";\r
+ break;\r
+ case AGGREGATE.AVG:\r
+ agg = "avg";\r
+ break;\r
+ case AGGREGATE.MIN:\r
+ agg = "min";\r
+ break;\r
+ case AGGREGATE.MAX:\r
+ agg = "max";\r
+ break;\r
+ case AGGREGATE.COUNT:\r
+ agg = "count";\r
+ break;\r
+ case AGGREGATE.STDEV:\r
+ agg = "stdev";\r
+ break;\r
+ case AGGREGATE.VAR:\r
+ agg = "var";\r
+ break;\r
+ default:\r
+ throw new NotImplementedException ();\r
+ }\r
+ \r
+ \r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf (agg);\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf (agg, oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+\r
+ }\r
+ \r
+ private bool FindSumElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("sum");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("sum", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindAvgElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("avg");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("avg", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindMinElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("min");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("min", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindMaxElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("max");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("max", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindCountElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("count");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("count", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindStdevElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("stdev");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("stdev", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindVarElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("var");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("var", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindLenElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("len");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("len", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindIifElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("iif");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("iif", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindIsNullElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("isnull");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("isnull", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+ \r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindSubstringElement (string s, string lower)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("substring");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("substring", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+\r
+ oldIndex = indexOf;\r
+ bool failed = false;\r
+\r
+ // Check is or part of column name\r
+ if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+ continue;\r
+\r
+ // is the element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ private bool FindInElement (string s, string lower, ref string s1, ref string s2)\r
+ {\r
+ string stemp = lower;\r
+ int indexOf = stemp.IndexOf ("in");\r
+\r
+ if (indexOf == -1)\r
+ return false;\r
+\r
+ int oldIndex = -1;\r
+ while ((indexOf = stemp.IndexOf ("in", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+ {\r
+ oldIndex = indexOf;\r
+ \r
+ // check is the 'and' element part of string element\r
+ if (IsPartOfStringElement (stemp, indexOf))\r
+ continue;\r
+\r
+\r
+ // Check is or part of something else for example column name\r
+ if (indexOf != 0) \r
+ { \r
+ if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+ continue;\r
+ }\r
+ \r
+ if (indexOf < stemp.Length + 2) \r
+ {\r
+ if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')\r
+ continue;\r
+ }\r
+\r
+ if (IsPartOfFunction (stemp, indexOf))\r
+ continue;\r
+\r
+ s1 = s.Substring (0, indexOf).Trim ();\r
+ s2 = s.Substring (indexOf + 2).Trim ();\r
+ return true;\r
+ }\r
+ \r
+ return false; \r
+ }\r
+\r
+ \r
+ #endregion // CheckElement methods\r
+\r
+ #region CreateElement methods\r
+\r
+ // \r
+ // These methods are going to be removed when way of parsing is changed\r
+ //\r
+\r
+ private void CreateOrElement (string s1, string s2, string inside) \r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionOr (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateAndElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionAnd (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateLikeElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionLike (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateInElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionIn (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateEqualsElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionEquals (s1.Trim (), s2.Trim ())); \r
+ }\r
+\r
+ private void CreateUnequalsElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionUnequals (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateLessThanElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionLessThan (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateLessThanOrEqualElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionLessThanOrEqual (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateGreaterThanElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionGreaterThan (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+\r
+ private void CreateGreaterThanOrEqualElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionGreaterThanOrEqual (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateAdditionElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2); \r
+ Elements.Add (new ExpressionAddition (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateSubtractionElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2); \r
+ Elements.Add (new ExpressionSubtraction (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateMultiplyElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionMultiply (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateDivideElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionDivide (s1.Trim (), s2.Trim ()));\r
+ }\r
+\r
+ private void CreateModulusElement (string s1, string s2, string inside)\r
+ {\r
+ CheckParenthesis (inside, ref s1, ref s2);\r
+ Elements.Add (new ExpressionModulus (s1.Trim (), s2.Trim ()));\r
+ } \r
+\r
+ #endregion // CreateElemnt methods\r
+\r
+ #region Little helppers\r
+\r
+ private void CheckParenthesis (string inside, ref string s1, ref string s2)\r
+ {\r
+ if (s1 == string.Empty && inside != string.Empty)\r
+ s1 = inside;\r
+ else if (s2 == string.Empty && inside != string.Empty)\r
+ s2 = inside; \r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Checks is the element part of stringelement\r
+ /// </summary>\r
+ private bool IsPartOfStringElement (string s, int indexOf)\r
+ {\r
+ // count how many '-charachters are before or. If count is odd it means or IS between quotes\r
+ int quotes = 0;\r
+ for (int i = indexOf - 1; i >= 0; i--) \r
+ {\r
+ if (s [i] == '\'')\r
+ quotes++;\r
+ }\r
+ \r
+ if ((quotes & 1) != 0)\r
+ return true;\r
+ else \r
+ return false;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Checks is the element part of column table\r
+ /// </summary>\r
+ private bool IsPartOfColumnName (string s, int indexOf)\r
+ {\r
+ for (int i = indexOf; i >= 0; i--) \r
+ {\r
+ \r
+ // If the element is between [] it is part of columnname\r
+ if (s [i] == '\'' || s [i] == ']') \r
+ {\r
+ break;\r
+ }\r
+ else if (s [i] == '[') \r
+ {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Checks are element part of function\r
+ /// </summary>\r
+ private bool IsPartOfFunction (string s, int indexOf)\r
+ {\r
+\r
+ // \r
+ // If ',' or '\'' comes before '(' this element is not part of function's parameters\r
+ //\r
+ \r
+ for (int i = indexOf; i >= 0; i--) \r
+ {\r
+ \r
+ if (s [i] == '(' || s [i] == ',') \r
+ {\r
+ return true;\r
+ }\r
+ else if (s [i] == ')') \r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ #endregion // Little helppers\r
+\r
+ #region ExpressionElementComparer\r
+ protected sealed class ExpressionElementComparer\r
+ {\r
+ object _value1 = null;\r
+ Type _t1 = null;\r
+ Type _RT1 = null;\r
+ DataRow _row = null;\r
+\r
+ public ExpressionElementComparer(ExpressionElement E1, DataRow Row)\r
+ {\r
+ _value1 = E1.Result (Row);\r
+\r
+ _row = Row;\r
+\r
+ if (_value1 == null || _value1 == DBNull.Value)\r
+ return;\r
+\r
+ _t1 = _value1.GetType ();\r
+ _RT1 = E1.ResultType (Row);\r
+ }\r
+\r
+ public int CompareTo (ExpressionElement E2)\r
+ {\r
+ object value1 = _value1;\r
+ object value2 = E2.Result (_row);\r
+\r
+ if ((value1 == null || value1 == DBNull.Value) && (value2 == null || value2 == DBNull.Value))\r
+ return 0;\r
+ else if (value2 == null || value2 == DBNull.Value)\r
+ return 1;\r
+ else if (value1 == null || value1 == DBNull.Value)\r
+ return -1;\r
+\r
+ Type t2 = value2.GetType ();\r
+ \r
+ Type RT2 = E2.ResultType (_row);\r
+\r
+ if (_t1 == typeof (string) || t2 == typeof (string)) \r
+ {\r
+ // FIXME: If one of elements are string they both should be???\r
+ return String.Compare(value1.ToString(), value2.ToString(), !_row.Table.CaseSensitive);\r
+ }\r
+\r
+ if (_t1 != t2) \r
+ {\r
+ value2 = Convert.ChangeType (value2, Type.GetTypeCode (_t1));\r
+ }\r
+\r
+ if (value1 is IComparable)\r
+ return ((IComparable)value1).CompareTo(value2);\r
+\r
+ return (int) _t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
+ BindingFlags.InvokeMethod, null, \r
+ value1, \r
+ new object [] {value2});\r
+ }\r
+ }\r
+ #endregion\r
+ } \r
+ #endif \r
+}\r