Various fixes to the Expression parser, the fixes include:
authorMiguel de Icaza <miguel@gnome.org>
Sat, 10 Sep 2011 02:02:46 +0000 (22:02 -0400)
committerMiguel de Icaza <miguel@gnome.org>
Sat, 10 Sep 2011 02:02:56 +0000 (22:02 -0400)
* Fixes to the SUBSTRING and TRIM function to allow
  a wider range of functions to be passed as
  parameters.   This fixes xamarin #665

* Fix to the Parser.jay grammar to eliminate the
  reduce/reduce conflicts.

* Dropping the string concatenation code and instead
  use the existing arithmetic addition operator which
  also fixes the concatenation operation in the presence
  of null values

* Adds the null literal

With the associated test cases.

mcs/class/System.Data/Makefile
mcs/class/System.Data/Mono.Data.SqlExpressions/Parser.jay
mcs/class/System.Data/Mono.Data.SqlExpressions/StringFunctions.cs
mcs/class/System.Data/Test/System.Data/DataColumnTest.cs

index 8990125c76923e5edc0570631c79d00e980b93bc..2c43f38c27f587f8160490acf65bd08d80936f9b 100644 (file)
@@ -63,7 +63,7 @@ EXTRA_DISTFILES = \
 BUILT_SOURCES = Mono.Data.SqlExpressions/Parser.cs
 
 Mono.Data.SqlExpressions/Parser.cs: Mono.Data.SqlExpressions/Parser.jay $(topdir)/jay/skeleton.cs
-       $(topdir)/jay/jay -ct < $(topdir)/jay/skeleton.cs $(CURDIR)/$< >$@
+       $(topdir)/jay/jay -vct < $(topdir)/jay/skeleton.cs $(CURDIR)/$< >$@
 
 include ../../build/library.make
 
index 613e4e2f8f828cd04c50bfcbd55b467a52f8f781..135b93651edc56cd720d5fd53467a6465f0b080f 100644 (file)
@@ -6,6 +6,7 @@
 //   Juraj Skripsky (juraj@hotfeet.ch)
 //
 // (C) 2004 HotFeet GmbH (http://www.hotfeet.ch)
+// Copyright 2011 Xamarin Inc (http://www.xamarin.com)
 //
 
 using System;
@@ -190,6 +191,7 @@ LiteralValue
        | NumberLiteral { $$ = new Literal ($1); }
        | DateLiteral           { $$ = new Literal ($1); }
        | BoolLiteral
+       | NULL          { $$ = new Literal (null); }
        ;
 
 BoolLiteral
@@ -271,28 +273,20 @@ AggFunctionName
        ;
 
 StringExpr
-       : PAROPEN StringExpr PARCLOSE
-       {
-               $$ = (IExpression)$2;
-       }
-       | SingleColumnValue
+       : SingleColumnValue
        | StringLiteral { $$ = new Literal ($1); }
-       | StringFunction
+       | Function
        ;
 
 StringFunction
-       : TRIM PAROPEN StringExpr PARCLOSE
+       : TRIM PAROPEN ArithExpr PARCLOSE
        {
                $$ = new TrimFunction ((IExpression)$3);
        }
-       | SUBSTRING PAROPEN StringExpr COMMA ArithExpr COMMA ArithExpr PARCLOSE
+       | SUBSTRING PAROPEN ArithExpr COMMA ArithExpr COMMA ArithExpr PARCLOSE
        {
                $$ = new SubstringFunction ((IExpression)$3, (IExpression)$5, (IExpression)$7);
        }
-       | StringExpr PLUS StringExpr
-       {
-               $$ = new ConcatFunction ((IExpression)$1, (IExpression)$3);
-       }
        ;
 
 CalcFunction
index 6d7c541f8b49d4d630611958020ed41a29391949..e64f8eb5e91169756103f0d8cb3fa5a548a3b3a3 100644 (file)
@@ -55,42 +55,6 @@ namespace Mono.Data.SqlExpressions {
                }
        }
 
-       internal class ConcatFunction : StringFunction
-       {
-               readonly IExpression _add;
-               public ConcatFunction (IExpression e, IExpression add)
-                       : base (e)
-               {
-                       _add = add;
-               }
-
-               public override bool Equals(object obj)
-               {
-                       if (!base.Equals (obj))
-                               return false;
-
-                       if (!(obj is ConcatFunction))
-                               return false;
-
-                       ConcatFunction other = (ConcatFunction) obj;
-                       return _add.Equals (other._add);
-               }
-
-               public override int GetHashCode()
-               {
-                       int hashCode = base.GetHashCode ();
-                       hashCode ^= _add.GetHashCode ();
-                       return hashCode;
-               }
-
-               override public object Eval (DataRow row) {
-                       string str = (string) base.Eval (row);
-                       string x = (string) _add.Eval (row);
-
-                       return str + x;
-               }
-       }
-       
        internal class SubstringFunction : StringFunction {
                IExpression start;
                IExpression len;
index e3ed8160e94aaccf9573408dc0d705a0e51d766a..ac7ceebb4cee87fe6aa45b5b11bd98cdc6fccb34 100644 (file)
 // (C) Copyright 2002 Rodrigo Moya
 // (C) Copyright 2003 Daniel Morgan
 // (C) Copyright 2003 Martin Willemoes Hansen
-//
+// (C) Copyright 2011 Xamarin Inc
 
 //
+// Copyright 2011 Xamarin Inc (http://www.xamarin.com)
 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -913,5 +914,46 @@ namespace MonoTests.System.Data
                                Assert.Fail ("SetOrdinalTest failed");
                        }
                }
+
+               [Test]
+               public void Xamarin665 ()
+               {
+                       var t = new DataTable() ;
+                       var c1 = t.Columns.Add ("c1");
+                       var c2 = t.Columns.Add ("c2");
+                       c2.Expression = "TRIM(ISNULL(c1,' '))";
+                       c2.Expression = "SUBSTRING(ISNULL(c1,' '), 1, 10)";
+               }
+
+               DataColumn MakeColumn (string col, string test)
+               {
+                       return new DataColumn () {
+                               ColumnName = col,
+                               Expression = test
+                       };
+               }
+
+#if false
+// Check Windows output for the row [0] value
+               [Test]
+               public void NullStrings ()
+               {
+                       var a = MakeColumn ("nullbar", "null+'bar'");
+                       var b = MakeColumn ("barnull", "'bar'+null");
+                       var c = MakeColumn ("foobar", "'foo'+'bar'");
+
+                       var table = new DataTable();
+                       
+                       table.Columns.Add(a);
+                       table.Columns.Add(b);
+                       table.Columns.Add(c);
+               
+                       var row = table.NewRow();
+                       table.Rows.Add(row);
+                       Assert.AreEqual (row [0], DBNull.Value, "#1");
+                       Assert.AreEqual (row [1], DBNull.Value, "#2");
+                       Assert.AreEqual (row [2], "foobar", "#3");
+               }
+#endif
        }
 }