-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow multiple relationships in ConnectorType #2747
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,23 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.PowerFx.Types; | ||
|
||
namespace Microsoft.PowerFx.Connectors | ||
{ | ||
public static class CdpExtensions | ||
{ | ||
public static bool TryGetFieldExternalTableName(this RecordType recordType, string fieldName, out string tableName, out string foreignKey) | ||
public static bool TryGetFieldRelationships(this RecordType recordType, string fieldName, out IEnumerable<ConnectorRelationship> relationships) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
if (recordType is not CdpRecordType cdpRecordType) | ||
if (recordType is not CdpRecordType cdpRecordType || (!cdpRecordType.TryGetFieldRelationships(fieldName, out relationships) && relationships.Any())) | ||
{ | ||
tableName = null; | ||
foreignKey = null; | ||
relationships = null; | ||
return false; | ||
} | ||
} | ||
|
||
return cdpRecordType.TryGetFieldExternalTableName(fieldName, out tableName, out foreignKey); | ||
return true; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
using Microsoft.PowerFx.Core.Utils; | ||
|
||
namespace Microsoft.PowerFx.Connectors | ||
{ | ||
public class ConnectorRelationship | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for now, yes |
||
{ | ||
public string ForeignTable { get; internal init; } | ||
|
||
public string ForeignKey { get; internal init; } | ||
|
||
public override int GetHashCode() | ||
{ | ||
return Hashing.CombineHash(ForeignTable?.GetHashCode() ?? 0, ForeignKey?.GetHashCode() ?? 0); | ||
} | ||
|
||
public override string ToString() => $"{ForeignTable ?? "<null>"}:{ForeignKey ?? "<null>"}"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,7 @@ namespace Microsoft.PowerFx.Connectors | |
// FormulaType is used to represent the type of the parameter in the Power Fx expression as used in Power Apps | ||
// ConnectorType contains more details information coming from the swagger file and extensions | ||
[DebuggerDisplay("{FormulaType._type}")] | ||
public class ConnectorType : SupportsConnectorErrors | ||
public class ConnectorType : SupportsConnectorErrors, IEquatable<ConnectorType> | ||
LucGenetier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
// "name" | ||
public string Name { get; internal set; } | ||
|
@@ -112,11 +112,9 @@ public class ConnectorType : SupportsConnectorErrors | |
internal ISwaggerSchema Schema { get; private set; } = null; | ||
|
||
// Relationships to external tables | ||
internal List<string> ExternalTables { get; set; } | ||
internal IEnumerable<ConnectorRelationship> ExternalTables => _externalTables; | ||
|
||
internal string RelationshipName { get; set; } | ||
LucGenetier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
internal string ForeignKey { get; set; } | ||
private List<ConnectorRelationship> _externalTables; | ||
|
||
internal ConnectorType(ISwaggerSchema schema, ISwaggerParameter openApiParameter, FormulaType formulaType, ErrorResourceKey warning = default) | ||
{ | ||
|
@@ -148,9 +146,11 @@ internal ConnectorType(ISwaggerSchema schema, ISwaggerParameter openApiParameter | |
// SalesForce only | ||
if (schema.ReferenceTo != null && schema.ReferenceTo.Count == 1) | ||
{ | ||
ExternalTables = new List<string>(schema.ReferenceTo); | ||
RelationshipName = schema.RelationshipName; | ||
ForeignKey = null; // SalesForce doesn't provide it, defaults to "Id" | ||
_externalTables = schema.ReferenceTo.Select(r => new ConnectorRelationship() | ||
{ | ||
ForeignTable = r, | ||
ForeignKey = null // Seems to always be Id | ||
}).ToList(); | ||
} | ||
|
||
Fields = Array.Empty<ConnectorType>(); | ||
|
@@ -290,12 +290,18 @@ internal DisplayNameProvider DisplayNameProvider | |
|
||
private DisplayNameProvider _displayNameProvider; | ||
|
||
internal void SetRelationship(SqlRelationship relationship) | ||
internal void SetRelationships(IEnumerable<SqlRelationship> relationships) | ||
{ | ||
ExternalTables ??= new List<string>(); | ||
ExternalTables.Add(relationship.ReferencedTable); | ||
RelationshipName = relationship.RelationshipName; | ||
ForeignKey = relationship.ReferencedColumnName; | ||
_externalTables ??= new List<ConnectorRelationship>(); | ||
|
||
foreach (SqlRelationship relationship in relationships) | ||
{ | ||
_externalTables.Add(new ConnectorRelationship() | ||
{ | ||
ForeignTable = relationship.ReferencedTable, | ||
ForeignKey = relationship.ReferencedColumnName | ||
}); | ||
} | ||
} | ||
|
||
private void AggregateErrors(ConnectorType[] types) | ||
|
@@ -336,5 +342,92 @@ private Dictionary<string, FormulaValue> GetEnum() | |
|
||
return enumDisplayNames.Zip(enumValues, (dn, ev) => new KeyValuePair<string, FormulaValue>(dn, ev)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); | ||
} | ||
|
||
public bool Equals(ConnectorType other) | ||
{ | ||
if (other == null) | ||
{ | ||
return false; | ||
} | ||
|
||
return this.Name == other.Name && | ||
LucGenetier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
this.DisplayName == other.DisplayName && | ||
this.Description == other.Description && | ||
this.IsRequired == other.IsRequired && | ||
Enumerable.SequenceEqual((IList<ConnectorType>)this.Fields ?? Array.Empty<ConnectorType>(), (IList<ConnectorType>)other.Fields ?? Array.Empty<ConnectorType>()) && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
Enumerable.SequenceEqual((IList<ConnectorType>)this.HiddenFields ?? Array.Empty<ConnectorType>(), (IList<ConnectorType>)other.HiddenFields ?? Array.Empty<ConnectorType>()) && | ||
this.ExplicitInput == other.ExplicitInput && | ||
this.IsEnum == other.IsEnum && | ||
Enumerable.SequenceEqual((IList<FormulaValue>)this.EnumValues ?? Array.Empty<FormulaValue>(), (IList<FormulaValue>)other.EnumValues ?? Array.Empty<FormulaValue>()) && | ||
Enumerable.SequenceEqual((IList<string>)this.EnumDisplayNames ?? Array.Empty<string>(), (IList<string>)other.EnumDisplayNames ?? Array.Empty<string>()) && | ||
this.Visibility == other.Visibility && | ||
((this.Capabilities == null && other.Capabilities == null) || this.Capabilities.Equals(other.Capabilities)) && | ||
this.KeyType == other.KeyType && | ||
this.KeyOrder == other.KeyOrder && | ||
this.Permission == other.Permission && | ||
this.NotificationUrl == other.NotificationUrl && | ||
((this.HiddenRecordType == null && other.HiddenRecordType == null) || this.HiddenRecordType.Equals(other.HiddenRecordType)) && | ||
this.Binary == other.Binary && | ||
this.MediaKind == other.MediaKind && | ||
Enumerable.SequenceEqual((IList<string>)this.ExternalTables ?? Array.Empty<string>(), (IList<string>)other.ExternalTables ?? Array.Empty<string>()); | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
return Equals(obj as ConnectorType); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
int h = Hashing.CombineHash(Name.GetHashCode(), DisplayName?.GetHashCode() ?? 0, Description?.GetHashCode() ?? 0, IsRequired.GetHashCode()); | ||
|
||
if (Fields != null) | ||
{ | ||
foreach (ConnectorType field in Fields) | ||
{ | ||
h = Hashing.CombineHash(h, field.GetHashCode()); | ||
} | ||
} | ||
|
||
if (HiddenFields != null) | ||
{ | ||
foreach (ConnectorType hiddenField in HiddenFields) | ||
{ | ||
h = Hashing.CombineHash(h, hiddenField.GetHashCode()); | ||
} | ||
} | ||
|
||
h = Hashing.CombineHash(h, ExplicitInput.GetHashCode(), IsEnum.GetHashCode(), Visibility.GetHashCode()); | ||
|
||
if (EnumValues != null) | ||
{ | ||
foreach (FormulaValue enumValue in EnumValues) | ||
{ | ||
h = Hashing.CombineHash(h, enumValue.GetHashCode()); | ||
} | ||
} | ||
|
||
if (EnumDisplayNames != null) | ||
{ | ||
foreach (string enumDisplayName in EnumDisplayNames) | ||
{ | ||
h = Hashing.CombineHash(h, enumDisplayName.GetHashCode()); | ||
} | ||
} | ||
|
||
h = Hashing.CombineHash(h, Capabilities.GetHashCode(), KeyType.GetHashCode(), KeyOrder.GetHashCode(), Permission.GetHashCode(), NotificationUrl?.GetHashCode() ?? 0, HiddenRecordType.GetHashCode()); | ||
h = Hashing.CombineHash(h, Binary.GetHashCode()); | ||
h = Hashing.CombineHash(h, MediaKind.GetHashCode()); | ||
|
||
if (ExternalTables != null) | ||
{ | ||
foreach (ConnectorRelationship relationship in ExternalTables) | ||
{ | ||
h = Hashing.CombineHash(h, relationship.GetHashCode()); | ||
} | ||
} | ||
|
||
return h; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text.Json.Serialization; | ||
|
@@ -12,7 +13,7 @@ | |
|
||
namespace Microsoft.PowerFx.Connectors | ||
{ | ||
internal sealed class ColumnCapabilities : ColumnCapabilitiesBase, IColumnsCapabilities | ||
internal sealed class ColumnCapabilities : ColumnCapabilitiesBase, IColumnsCapabilities, IEquatable<ColumnCapabilities> | ||
{ | ||
[JsonInclude] | ||
[JsonPropertyName(CapabilityConstants.ColumnProperties)] | ||
|
@@ -72,5 +73,32 @@ public static ColumnCapabilities ParseColumnCapabilities(IDictionary<string, IOp | |
IsChoice = isChoice | ||
}); | ||
} | ||
|
||
public bool Equals(ColumnCapabilities other) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
return Enumerable.SequenceEqual((IEnumerable<KeyValuePair<string, ColumnCapabilitiesBase>>)this._childColumnsCapabilities ?? Array.Empty<KeyValuePair<string, ColumnCapabilitiesBase>>(), (IEnumerable<KeyValuePair<string, ColumnCapabilitiesBase>>)other._childColumnsCapabilities ?? Array.Empty<KeyValuePair<string, ColumnCapabilitiesBase>>()) && | ||
this.Capabilities.Equals(other.Capabilities); | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
return Equals(obj as ColumnCapabilities); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
int h = Capabilities.GetHashCode(); | ||
|
||
if (_childColumnsCapabilities != null) | ||
{ | ||
foreach (KeyValuePair<string, ColumnCapabilitiesBase> kvp in _childColumnsCapabilities) | ||
{ | ||
h = Hashing.CombineHash(h, kvp.Key.GetHashCode()); | ||
h = Hashing.CombineHash(h, kvp.Value.GetHashCode()); | ||
} | ||
} | ||
|
||
return h; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we just want to remove this at the editorconfig level?