#At file:///C:/Users/Reggie/work/connector-net/trunk/ based on revid:julio.casal@stripped8k0bjzfc9
987 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 20:05:47 +0000
+++ b/CHANGES 2011-05-24 01:53:58 +0000
@@ -16,6 +16,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
6.4.0
- Implemented Cache Server Properties connection option
=== 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-20110524015522-x2im2ql44do8hxoc.bundle
| Thread |
|---|
| • bzr commit into connector-net-trunk branch (reggie.burnett:987) | Reggie Burnett | 24 May |