[Dbix-class] rfc, treating NULL as a value like any other

Darren Duncan darren at DarrenDuncan.net
Mon Jan 28 21:51:20 GMT 2008


At 3:59 PM +0000 1/28/08, Matt S Trout wrote:
>On Sat, Jan 26, 2008 at 07:35:08PM -0800, Darren Duncan wrote:
>>  Under my proposal, saying "foo != 3" would return foo that are NULL,
>>  because they are not 3.
>
>If you're going to have something that behaves like that, please don't call
>it NULL.

Just as well that I actually called the corresponding concept Nothing, then.

I also realize that in practice users probably would rarely if ever 
face the situation where saying "foo = 3" would do what they wanted 
and saying "foo != 3" with the same foo would also return foo of 
Nothing.

Any typical situation where they would simply say "foo = 3" is a 
situation where foo is not nullable, and hence their saying "foo != 
3" would never return Nothing anyway.  So this behaviour should be 
intuitive to SQL users.

For a typical situation where foo is nullable, users would not simply 
be treating foo like a normal value; instead they would be asking one 
of these 3 questions, though usually not directly: "foo = Nothing", 
"foo != Nothing and foo.attr = 3", "foo != Nothing and foo.attr != 
3"; this would be similar to how Perl code may test for foo being 
undef before it tries using foo in a normal context.

In actual select-like queries, for a not-nullable foo, you'd say 
something analagous to:

   myrowset.where:{ .foo = 3 }

or

   myrowset.where:{ .foo != 3 }

... whereas for a nullable foo, you'd say something analagous to:

   myrowset.where:{ .foo = Nothing }

or

   myrowset.ungroup_to_outer_name('foo').where:{ .foo = 3 }

or

   myrowset.ungroup_to_outer_name('foo').where:{ .foo != 3 }

... in order to match not-nullable foo equal or not equal to 3.

To explain the above, the type of foo in the not-nullable case is 
Int, while the type of foo in the nullable case is Maybe{Int}, and a 
Maybe is a rowset having zero or 1 row, and 1 column.  A relational 
ungroup on a table-valued column will eliminate any main rowset rows 
where the inner table value had zero rows (that equalled Nothing in 
this case), and then for the remaining rows, the type of foo is now 
just Int like the not nullable case (if the inner table had more than 
1 row, not the case for Maybe, then extra rows are added to the 
result for each, like when you do an inner join).

Now once again, the real syntax could be made more terse, but the 
example is meant to be illustrative of the fact that you use 
different syntax to work with nullable vs not-nullable, and none of 
them look like a plain "foo != 3" that also returns null.

-- Darren Duncan



More information about the DBIx-Class mailing list