SimplifyNullChecks

io.getquill.norm.SimplifyNullChecks
class SimplifyNullChecks(equalityBehavior: EqualityBehavior) extends StatelessTransformer

Due to the introduction of null checks in map, flatMap, and exists, in FlattenOptionOperation in order to resolve #1053, as well as to support non-ansi compliant string concatenation as outlined in #1295, large conditional composites became common. For example:

 case class
Holder(value:Option[String])

// The following statement query[Holder].map(h => h.value.map(_ + "foo")) //
Will yield the following result SELECT CASE WHEN h.value IS NOT NULL THEN
h.value || 'foo' ELSE null END FROM Holder h 

Now, let's add a getOrElse statement to the clause that requires an additional wrapped null check. We cannot rely on there being a map call beforehand since we could be reading value as a nullable field directly from the database).

 // The following statement
query[Holder].map(h => h.value.map(_ + "foo").getOrElse("bar")) // Yields the
following result: SELECT CASE WHEN CASE WHEN h.value IS NOT NULL THEN h.value
\|| 'foo' ELSE null END IS NOT NULL THEN CASE WHEN h.value IS NOT NULL THEN
h.value || 'foo' ELSE null END ELSE 'bar' END FROM Holder h 
This of course is highly redundant and can be reduced to simply:
SELECT CASE WHEN h.value IS NOT NULL AND (h.value || 'foo') IS NOT NULL THEN
h.value || 'foo' ELSE 'bar' END FROM Holder h 
This reduction is done by the "Center Rule." There are some other simplification rules as well. Note how we are force to null-check both `h.value` as well as `(h.value || 'foo')` because a user may use `Option[T].flatMap` and explicitly transform a particular value to `null`.

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any

Members list

Type members

Classlikes

object Optional

Simple extractor that looks inside of an optional values to see if the thing inside can be pulled out. If not, it just returns whatever element it can find.

Simple extractor that looks inside of an optional values to see if the thing inside can be pulled out. If not, it just returns whatever element it can find.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
Optional.type
object `== or !=`

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
`== or !=`.type

Value members

Concrete methods

override def apply(ast: Ast): Ast

Attributes

Definition Classes

Inherited methods

def apply(e: Action): Action

Attributes

Inherited from:
StatelessTransformer
def apply(e: Target): Target

Attributes

Inherited from:
StatelessTransformer
def apply(e: Action): Action

Attributes

Inherited from:
StatelessTransformer
def apply(e: Value): Value

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer
def apply(e: Query): Query

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer

Attributes

Inherited from:
StatelessTransformer
def applyIdent(id: Ident): Ident

Attributes

Inherited from:
StatelessTransformer