Skip to content

Fix list type mapping#542

Merged
austindrenski merged 1 commit intonpgsql:devfrom
austindrenski:xml-docs-and-refactors
Jul 25, 2018
Merged

Fix list type mapping#542
austindrenski merged 1 commit intonpgsql:devfrom
austindrenski:xml-docs-and-refactors

Conversation

@austindrenski
Copy link
Contributor

@austindrenski austindrenski commented Jul 25, 2018

Moved from #541.

@austindrenski austindrenski force-pushed the xml-docs-and-refactors branch from 8adda02 to 9a993e3 Compare July 25, 2018 03:25
@austindrenski austindrenski changed the title Fix list type mapping + refactors from 541 Fix list type mapping Jul 25, 2018
@austindrenski
Copy link
Contributor Author

austindrenski commented Jul 25, 2018

The diff is large, but these are the only substantial changes:

+    /// <inheritdoc />
      protected NpgsqlListTypeMapping(RelationalTypeMappingParameters parameters, RelationalTypeMapping elementMapping)
-        : base(parameters) {}
+        : base(parameters)
+        => ElementMapping = elementMapping;
-    if (arr.Rank != 1)
+    if (list.GetType().GenericTypeArguments[0] != ElementMapping.ClrType)
          throw new NotSupportedException("Multidimensional array literals aren't supported");
 
     var sb = new StringBuilder();
     sb.Append("ARRAY[");
-    for (var i = 0; i < arr.Length; i++)
+    for (var i = 0; i < list.Count; i++)

@austindrenski austindrenski merged commit c4a8e30 into npgsql:dev Jul 25, 2018
@austindrenski austindrenski deleted the xml-docs-and-refactors branch July 25, 2018 04:29
{
// TODO: Duplicated from NpgsqlArrayTypeMapping
var arr = (Array)value;
var list = (IList)value;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@austindrenski I'm not too sure about this...

For one thing multidimensional arrays seem to implement List - but not List<T>. This is odd, and I suspect it to be .NET legacy behavior which was kept to maintain backwards compatibility.

At the very least, please add a specific check for multidimensional arrays, throwing NotSupportedException - it's an error to render a multidimensional .NET array as a one-dimensional PostgreSQL array...

(it would have been better to allow reviewing this non-cosmetic change before merging, but no big deal :)).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly, I wasn't thinking about multidimensional arrays here...which underscores your point about reviews—that's my bad.

Since we don't support jagged arrays, I assumed that List<T> would only be mappable to one-dimensional PostgreSQL arrays. (Since List<List<T>> is more or less the equivalent of T[][].)

Did you have something else in mind?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See some additional thoughts in #552 (comment).

As I wrote there, we basically need to separate between multidimensional arrays and jagged arrays. The latter really aren't supported by PostgreSQL and a clear, informative message should say so. I agree that List<List<T> is just another form of a jagged array and should throw in the same way.

There's no such thing as a multidimensional array with List<T>, so I don't think you need to think about that here in NpgsqlListTypeMapping (as opposed to NpgsqlArrayTypeMapping).

Aside from that, I'm simply not sure there's value in support non-generic List - I'm assuming part of you change was to support that. It's probably healthier to restrict support to generic List<T> only.

Hope this is clear, we're discussing several different things here...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I think we're on the same page. But I'm still a little lost on what you mean by the non-generic List:

Aside from that, I'm simply not sure there's value in support non-generic List - I'm assuming part of you change was to support that.

  1. My understanding is that we will only support List<T> where T is not a collection type.
  2. I cast the incoming parameter to IList so that I could access IList.Count for the loop below.
    • I'm using IList since the type mapper is non-generic, so there's no type parameter in scope for IList<T>/List<T>.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wasn't very clear on that.

First, I'd rather we had a clear up-front check that GenerateNonNullSqlLiteral() gets the right kind of input, i.e. a generic List<T> where T corresponds to ElementMapping. Right now we throw with imprecise messages (multidimensional arrays, or just that the given object isn't a generic type).

Second, as I wrote in the other comment, I'd rather we had construction-time checks for the correctness of the mapping object itself, i.e. throw if we attempt to construct a mapping that would correspond to a jagged array (i.e. T[][], List<List<T>>).

After all these checks it seems fine to cast to IList as we've verified that the types are correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. I'll put something together in the next few days.

static List<TElem> Snapshot(List<TElem> source, ValueComparer<TElem> elementComparer)
{
if (source == null)
if (source is null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any specific reason to convert x == null to x is null? It makes sense if you use pattern matching (i.e. x is null y) but just for null checking? I'd stick to the current standard syntax rather than starting to change the entire codebase etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a fair point. I tend to make these changes out of habit more than anything else.

I'll revert this in an upcoming commit. (This type mapper still lacks type-casting for the array literals.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants