Skip to content
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 arrays containing null to be serialized #698

Merged
merged 1 commit into from
Feb 14, 2017
Merged

Conversation

sgrif
Copy link
Member

@sgrif sgrif commented Feb 13, 2017

Deserialization already worked, so there's no reason we shouldn't just
allow this. It's worth noting that there is no way to represent whether
an array is allowed to contain nulls or not within postgres's type
system. As such, the type Array<Nullable<ST>> will never be generated
by infer_schema! (I do want to make FromSql<Array<ST>> for Vec<Option>just work though). Since we never provide aToSql<Array> for Vec<Option>`, Diesel will prevent you from
accidentally inserting nulls at compile time. Ultimately the user does
just have to make sure they represent whether the array could contain
null in the output type, however.

One alternative would be to represent the fact that all arrays can
contain null within the type system, and only provide impl FromSql<Array<ST>> for Vec<Option<T>>. I suspect this would hinder
ergonomics pretty heavily, but we should consider it before 1.0.

One note about the implementation -- Technically we should be setting
flags to 1 if the array contains any nulls, as that's what happens
on the data sent to us. However, setting it would require us to perform
an additional level of intermediate buffering on all the values to
determine whether the flag should be set, and that flag is currently
ignored by PG. "But Sean, that's just relying on an implementation
detail!" this is true, but our entire usage of the binary format is
relying on an implementation detail (See #695).

@sgrif sgrif requested a review from killercup February 13, 2017 16:50
Copy link
Member

@killercup killercup left a comment

Choose a reason for hiding this comment

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

LGTM (I trust you on the -1 == Null, looks very C-y and thus believable.)

try!(out.write_all(&buffer));
buffer.clear();
} else {
try!(out.write_i32::<NetworkEndian>(-1));
Copy link
Member

Choose a reason for hiding this comment

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

I'm not familiar with Postgres' binary interface, so this is one of the places where I'd really like to have a link to some semi-official Postgres document that says "-1 is null here".

Copy link
Member Author

Choose a reason for hiding this comment

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

I can link to the line in the source code? There is no documentation on this. But we also have

if has_null && elem_size == -1 {
T::from_sql(None)
} else {
;)

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Yes! It even points to something with postgres in the name! Perfect! 😄

No, but seriously, it helps see where this comes from (and where to look when something changed).

Deserialization already worked, so there's no reason we shouldn't just
allow this. It's worth noting that there is no way to represent whether
an array is allowed to contain nulls or not within postgres's type
system. As such, the type `Array<Nullable<ST>>` will never be generated
by `infer_schema!` (I do want to make `FromSql<Array<ST>> for
`Vec<Option<T>>` just work though). Since we never provide a
`ToSql<Array<ST>> for Vec<Option<T>>`, Diesel will prevent you from
accidentally inserting nulls at compile time. Ultimately the user does
just have to make sure they represent whether the array could contain
null in the output type, however.

One alternative would be to represent the fact that all arrays can
contain null within the type system, and only provide `impl
FromSql<Array<ST>> for Vec<Option<T>>`. I suspect this would hinder
ergonomics pretty heavily, but we should consider it before 1.0.

One note about the implementation -- Technically we should be setting
`flags` to `1` if the array contains any nulls, as that's what happens
on the data sent to us. However, setting it would require us to perform
an additional level of intermediate buffering on all the values to
determine whether the flag should be set, and that flag is currently
ignored by PG. "But Sean, that's just relying on an implementation
detail!" this is true, but our entire usage of the binary format is
relying on an implementation detail (See #695).
@sgrif sgrif force-pushed the sg-arrays-of-null branch from 3d985d7 to a571e41 Compare February 14, 2017 11:12
@sgrif sgrif merged commit 01de078 into master Feb 14, 2017
@sgrif sgrif deleted the sg-arrays-of-null branch February 14, 2017 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants