List:Commits« Previous MessageNext Message »
From:Reggie Burnett Date:May 24 2011 1:47am
Subject:bzr commit into connector-net-6.2 branch (reggie.burnett:936)
View as plain text  
#At file:///C:/Users/Reggie/work/connector-net/6.2/ based on revid:julio.casal@strippedcgoqcm6

  936 Reggie Burnett	2011-05-23 [merge]
      merge

    modified:
      CHANGES
      MySql.Data.Entity/Provider/Fragments/InputFragment.cs
      MySql.Data.Entity/Provider/Fragments/SqlFragment.cs
      MySql.Data.Entity/Provider/Generators/SqlGenerator.cs
      MySql.Data.Entity/Provider/Statements/SelectStatement.cs
      MySql.Data.Entity/Tests/JoinTests.cs
      MySql.Data.Entity/Tests/Properties/SQLSyntax.Designer.cs
      MySql.Data.Entity/Tests/Properties/SQLSyntax.resx
=== modified file 'CHANGES'
=== modified file 'CHANGES'
--- a/CHANGES	2011-05-19 19:28:42 +0000
+++ b/CHANGES	2011-05-24 01:47:48 +0000
@@ -48,6 +48,7 @@
   are now hidden when running on the Compact Framework (MySQL bug #60600).
 - Fixed MembershipProvider to only return exact matches when calling GetUser(string username) and 
   GetUserNameByEmail (MySQL bug #61027, Oracle bug #12562287).
+- added the ability to raise a join on the right side of a join to a derived table in EF code generation
 
 Version 6.2.4
 - Fix authorization popup after modifying stored procedure in VS (Bug #44715)

=== modified file 'MySql.Data.Entity/Provider/Fragments/InputFragment.cs'
--- a/MySql.Data.Entity/Provider/Fragments/InputFragment.cs	2011-03-03 18:01:04 +0000
+++ b/MySql.Data.Entity/Provider/Fragments/InputFragment.cs	2011-05-24 01:47:48 +0000
@@ -27,7 +27,7 @@
 
 namespace MySql.Data.Entity
 {
-    abstract class InputFragment : SqlFragment 
+    abstract class InputFragment : SqlFragment
     {
         // not all input classes will support two inputs but union and join do
         // in cases where only one input is used, Left is it
@@ -75,5 +75,14 @@
                 (IsWrapped && !(this is JoinFragment)))
                 sql.AppendFormat(" AS {0}", QuoteIdentifier(Name));
         }
+
+        public ColumnFragment GetColumnFromProperties(PropertyFragment properties)
+        {
+            ColumnFragment col = Left.GetColumnFromProperties(properties);
+            if (col == null)
+                col = Right.GetColumnFromProperties(properties);
+            return col;
+        }
     }
 }
+

=== modified file 'MySql.Data.Entity/Provider/Fragments/SqlFragment.cs'
--- a/MySql.Data.Entity/Provider/Fragments/SqlFragment.cs	2011-04-20 18:40:38 +0000
+++ b/MySql.Data.Entity/Provider/Fragments/SqlFragment.cs	2011-05-24 01:47:48 +0000
@@ -163,6 +163,18 @@
             cf.Literal = Literal;
             return cf;
         }
+
+        public override bool Equals(object obj)
+        {
+            if (!(obj is ColumnFragment)) return false;
+            ColumnFragment column = obj as ColumnFragment;
+            if (column.PropertyFragment != null && PropertyFragment != null)
+                return column.PropertyFragment.Equals(PropertyFragment);
+            if (column.TableName != TableName) return false;
+            if (column.ColumnName != ColumnName) return false;
+            if (column.ColumnAlias != ColumnAlias) return false;
+            return true;
+        }
     }
 
     internal class ExistsFragment : NegatableFragment
@@ -300,6 +312,33 @@
         {
             get { return Properties.Count == 0 ? null : Properties[Properties.Count - 1]; }
         }
+
+        public void Trim(string name)
+        {
+            int index = Properties.LastIndexOf(name);
+            Properties.RemoveRange(index + 1, Properties.Count - index - 1);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (!(obj is PropertyFragment)) return false;
+            PropertyFragment prop = obj as PropertyFragment;
+            Debug.Assert(Properties != null &&  prop.Properties != null);
+
+            int aIndex = Properties.Count - 1;
+            int bIndex = prop.Properties.Count - 1;
+            while (aIndex >= 0 && bIndex >= 0)
+                if (String.Compare(Properties[aIndex--], prop.Properties[bIndex--], true) != 0) return false;
+            return true;
+        }
+
+        public PropertyFragment Clone()
+        {
+            PropertyFragment newPF = new PropertyFragment();
+            foreach (string prop in Properties)
+                newPF.Properties.Add(prop);
+            return newPF;
+        }
     }
 
     internal class SortFragment : SqlFragment
@@ -336,5 +375,16 @@
             sql.Append(Distinct ? " UNION DISTINCT " : " UNION ALL ");
             Right.WriteSql(sql);
         }
+
+        public bool HasDifferentNameForColumn(ColumnFragment column)
+        {
+            Debug.Assert(Left is SelectStatement);
+            Debug.Assert(Right is SelectStatement);
+            if ((Left as SelectStatement).HasDifferentNameForColumn(column))
+                return true;
+            return (Right as SelectStatement).HasDifferentNameForColumn(column);
+        }
     }
+
+
 }

=== modified file 'MySql.Data.Entity/Provider/Generators/SqlGenerator.cs'
--- a/MySql.Data.Entity/Provider/Generators/SqlGenerator.cs	2011-04-20 18:40:38 +0000
+++ b/MySql.Data.Entity/Provider/Generators/SqlGenerator.cs	2011-05-24 01:47:48 +0000
@@ -83,12 +83,26 @@
 
             ColumnFragment column = new ColumnFragment(null, fragment.LastProperty);
             column.PropertyFragment = fragment;
-            column.TableName = FindInputFromProperties(fragment);
-
+            InputFragment input = FindInputFromProperties(fragment);
+            if (input != null)
+                column.TableName = input.Name;
+
+            // now we need to check if our column name was possibly renamed
+            if (input is TableFragment) return column;
+
+            SelectStatement select = input as SelectStatement;
+            UnionFragment union = input as UnionFragment;
+
+            if (select != null)
+                select.HasDifferentNameForColumn(column);
+            else if (union != null)
+                union.HasDifferentNameForColumn(column);
+
+            // input is a table, selectstatement, or unionstatement
             return column;
         }
 
-        private string FindInputFromProperties(PropertyFragment fragment)
+        private InputFragment FindInputFromProperties(PropertyFragment fragment)
         {
             Debug.Assert(fragment != null);
             PropertyFragment propertyFragment = fragment as PropertyFragment;
@@ -101,12 +115,13 @@
                     string reference = propertyFragment.Properties[x];
                     InputFragment input = scope.GetFragment(reference);
                     if (input == null) continue;
-                    if (input.Scoped) return input.Name;
+                    if (input.Scoped) return input;
                     if (input is SelectStatement)
-                        return (input as SelectStatement).From.Name;
+                        return (input as SelectStatement).From;
                     continue;
                 }
             }
+            Debug.Fail("Should have found an input");
             return null;
         }
 

=== modified file 'MySql.Data.Entity/Provider/Statements/SelectStatement.cs'
--- a/MySql.Data.Entity/Provider/Statements/SelectStatement.cs	2011-04-20 18:40:38 +0000
+++ b/MySql.Data.Entity/Provider/Statements/SelectStatement.cs	2011-05-24 01:47:48 +0000
@@ -33,6 +33,7 @@
     class SelectStatement : InputFragment 
     {
         private Dictionary<string, ColumnFragment> columnHash;
+        private bool hasRenamedColumns;
 
         public SelectStatement() : base(null)
         {
@@ -132,7 +133,7 @@
         void AddDefaultColumns()
         {
 //            List<PropertyFragment> properties = GetColumnPropertiesFromInput(From);
-            AddDefaultColumnsForFragment(From);
+            AddDefaultColumnsForFragment(From, null);
         }
 
         //private List<PropertyFragment> GetColumnPropertiesFromInput(InputFragment input)
@@ -140,18 +141,22 @@
         //    if (input is TableFragment)
         //}
 
-        void AddDefaultColumnsForFragment(InputFragment input)
+        void AddDefaultColumnsForFragment(InputFragment input, PropertyFragment trail)
         {
+            if (trail == null)
+                trail = new PropertyFragment();
             if (input is TableFragment)
             {
-                AddDefaultColumnsForTable(input as TableFragment);
+                AddDefaultColumnsForTable(input as TableFragment, trail);
             }
             else if (input is JoinFragment || input is UnionFragment)
             {
+                trail.Properties.Add(input.Name);
                 if (input.Left != null)
-                    AddDefaultColumnsForFragment(input.Left);
+                    AddDefaultColumnsForFragment(input.Left, trail);
+                trail.Trim(input.Name);
                 if (input.Right != null)
-                AddDefaultColumnsForFragment(input.Right);
+                AddDefaultColumnsForFragment(input.Right, trail);
 
                 // if this input is scoped, then it is the base tablename for the columns
                 if (input.Scoped)
@@ -168,14 +173,19 @@
                 throw new NotImplementedException();
         }
 
-        void AddDefaultColumnsForTable(TableFragment table)
+        void AddDefaultColumnsForTable(TableFragment table, PropertyFragment trail)
         {
+            trail.Properties.Add(table.Name);
             if (columnHash == null)
                 columnHash = new Dictionary<string, ColumnFragment>();
 
             foreach (EdmProperty property in Metadata.GetProperties(table.Type.EdmType))
             {
+                PropertyFragment props = trail.Clone();
+                props.Properties.Add(property.Name);
+
                 ColumnFragment col = new ColumnFragment(table.Name, property.Name);
+                col.PropertyFragment = props;
                 if (table.Columns == null)
                     table.Columns = new List<ColumnFragment>();
                 table.Columns.Add(col);
@@ -193,6 +203,7 @@
         private string MakeColumnNameUnique(string baseName)
         {
             int i = 1;
+            hasRenamedColumns = true;
             while (true)
             {
                 string name = String.Format("{0}{1}", baseName, i);
@@ -201,6 +212,19 @@
             }
         }
 
+        public bool HasDifferentNameForColumn(ColumnFragment column)
+        {
+            if (!hasRenamedColumns) return false;
+            foreach (ColumnFragment c in Columns)
+            {
+                if (!c.Equals(column)) continue;
+                if (String.IsNullOrEmpty(c.ColumnAlias)) return false;
+                column.ColumnName = c.ColumnAlias;
+                return true;
+            }
+            return false;
+        }
+
         public bool IsCompatible(DbExpressionKind expressionKind)
         {
             switch (expressionKind)

=== modified file 'MySql.Data.Entity/Tests/JoinTests.cs'
--- a/MySql.Data.Entity/Tests/JoinTests.cs	2011-04-20 18:40:38 +0000
+++ b/MySql.Data.Entity/Tests/JoinTests.cs	2011-05-24 01:47:48 +0000
@@ -120,20 +120,51 @@
         }
 
         [Test]
+        public void JoinOfUnionsOnRightSideofJoin()
+        {
+            using (testEntities context = new testEntities())
+            {
+                string eSql = @"SELECT c.Id, c.Name, a.Id, a.Name, b.Id, b.Name FROM
+                                testEntities.Companies AS c JOIN (testEntities.Authors AS a
+                                JOIN testEntities.Books AS b ON a.Id = b.Id) ON c.Id = a.Id";
+                ObjectQuery<Company> query = context.CreateQuery<Company>(eSql);
+                string s= query.ToTraceString();
+
+
+                //var j1 = from store in context.Stores
+                //         join toy in context.Toys
+                //         on store.Id equals toy.Id
+                //         select new { store.Id, store.Name };
+                //var j2 = from a in context.Authors
+                //         join p in context.Publishers
+                //         on a.Id equals p.id
+                //         select new { a.Id, a.Name };
+                //var u1 = j1.Union(j2);
+                //var q = from book in context.Books
+                //        join u in j1.Union(j2)
+                //        on book.Id equals u.Id
+                //        select book;
+                //string sql = q.ToTraceString();
+                //CheckSql(sql, SQLSyntax.JoinOnRightSideAsDerivedTable);
+            }
+        }
+
+        [Test]
         public void JoinOnRightSideNameClash()
         {
-
             using (testEntities context = new testEntities())
             {
-                var inner = from a in context.Authors join s in context.Stores on a.Id equals s.Id select a;
-                var outer = from o in context.Orders join i in inner on o.Id equals i.Id select o;
-                string sql = outer.ToTraceString();
+                string eSql = @"SELECT c.Id, c.Name, a.Id, a.Name, b.Id, b.Name FROM
+                                testEntities.Companies AS c JOIN (testEntities.Authors AS a
+                                JOIN testEntities.Books AS b ON a.Id = b.Id) ON c.Id = a.Id";
+                ObjectQuery<DbDataRecord> query = context.CreateQuery<DbDataRecord>(eSql);
+                string sql = query.ToTraceString();
                 CheckSql(sql, SQLSyntax.JoinOnRightSideNameClash);
-                foreach (Order o in outer)
+                foreach (DbDataRecord record in query)
                 {
-                    double d = o.Freight;
+                    Assert.AreEqual(6, record.FieldCount);
                 }
             }
-        }
+       }
     }
 }
\ No newline at end of file

=== modified file 'MySql.Data.Entity/Tests/Properties/SQLSyntax.Designer.cs'
--- a/MySql.Data.Entity/Tests/Properties/SQLSyntax.Designer.cs	2011-04-20 18:36:21 +0000
+++ b/MySql.Data.Entity/Tests/Properties/SQLSyntax.Designer.cs	2011-05-24 01:43:31 +0000
@@ -1,7 +1,7 @@
 ∩╗-------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:2.0.50727.5420
+//     Runtime Version:2.0.50727.4959
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -220,19 +220,21 @@
         ///   Looks up a localized string similar to SELECT
         ///1 AS C1, 
         ///Extent1.Id, 
-        ///Extent1.Freight, 
-        ///Extent1.StoreId
-        ///FROM Orders AS Extent1 INNER JOIN (SELECT
+        ///Extent1.Name, 
+        ///Join1.Id AS Id1, 
+        ///Join1.Name AS Name1, 
+        ///Join1.Id1 AS Id2, 
+        ///Join1.Name1 AS Name2
+        ///FROM Companies AS Extent1 INNER JOIN (SELECT
         ///Extent2.Id, 
         ///Extent2.Name, 
         ///Extent2.Age, 
         ///Extent3.Id AS Id1, 
         ///Extent3.Name AS Name1, 
-        ///Extent3.Address, 
-        ///Extent3.City, 
-        ///Extent3.State, 
-        ///Extent3.ZipCode
-        ///FROM Authors AS Extent2 INNER JOIN Stores AS Extent3 ON (Extent2.Id = Extent3.Id) OR ((Extent2.Id IS  NULL) AND (Extent3.Id IS  NULL))) AS Join1 ON (Extent1.Id = Join1.Id) OR ((Extent1.Id IS  NULL) AND (Join1.Id IS  NULL)).
+        ///Extent3.Pages, 
+        ///Extent3.Author_id, 
+        ///Extent3.Publisher_id
+        ///FROM Authors AS Extent2 INNER JOIN Books AS Extent3 ON Extent2.Id = Extent3.Id) AS Join1 ON Extent1.Id = Join1.Id.
         /// </summary>
         internal static string JoinOnRightSideNameClash {
             get {
@@ -608,6 +610,15 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to .
+        /// </summary>
+        internal static string String1 {
+            get {
+                return ResourceManager.GetString("String1", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to SELECT
         ///GroupBy1.A1 AS C1
         ///FROM (SELECT

=== modified file 'MySql.Data.Entity/Tests/Properties/SQLSyntax.resx'
--- a/MySql.Data.Entity/Tests/Properties/SQLSyntax.resx	2011-04-20 18:36:21 +0000
+++ b/MySql.Data.Entity/Tests/Properties/SQLSyntax.resx	2011-05-24 01:43:31 +0000
@@ -224,19 +224,21 @@
     <value>SELECT
 1 AS C1, 
 Extent1.Id, 
-Extent1.Freight, 
-Extent1.StoreId
-FROM Orders AS Extent1 INNER JOIN (SELECT
+Extent1.Name, 
+Join1.Id AS Id1, 
+Join1.Name AS Name1, 
+Join1.Id1 AS Id2, 
+Join1.Name1 AS Name2
+FROM Companies AS Extent1 INNER JOIN (SELECT
 Extent2.Id, 
 Extent2.Name, 
 Extent2.Age, 
 Extent3.Id AS Id1, 
 Extent3.Name AS Name1, 
-Extent3.Address, 
-Extent3.City, 
-Extent3.State, 
-Extent3.ZipCode
-FROM Authors AS Extent2 INNER JOIN Stores AS Extent3 ON (Extent2.Id = Extent3.Id) OR ((Extent2.Id IS  NULL) AND (Extent3.Id IS  NULL))) AS Join1 ON (Extent1.Id = Join1.Id) OR ((Extent1.Id IS  NULL) AND (Join1.Id IS  NULL))</value>
+Extent3.Pages, 
+Extent3.Author_id, 
+Extent3.Publisher_id
+FROM Authors AS Extent2 INNER JOIN Books AS Extent3 ON Extent2.Id = Extent3.Id) AS Join1 ON Extent1.Id = Join1.Id</value>
   </data>
   <data name="MaxInSubQuery1" xml:space="preserve">
     <value>SELECT
@@ -491,6 +493,9 @@
  ORDER BY 
 Project1.Name DESC LIMIT 2,2</value>
   </data>
+  <data name="String1" xml:space="preserve">
+    <value />
+  </data>
   <data name="SumSimple" xml:space="preserve">
     <value>SELECT
 GroupBy1.A1 AS C1

Attachment: [text/bzr-bundle] bzr/reggie.burnett@oracle.com-20110524014748-z2jskd9lvryb5i85.bundle
Thread
bzr commit into connector-net-6.2 branch (reggie.burnett:936) Reggie Burnett24 May