replaced NoCoalesce with NullFallback and updated tests
This commit is contained in:
@@ -218,7 +218,7 @@ func buildResolversExpr(
|
||||
expr = dbx.Enclose(dbx.And(expr, mm))
|
||||
} else if left.MultiMatchSubQuery != nil {
|
||||
mm := &manyVsOneExpr{
|
||||
noCoalesce: left.NoCoalesce,
|
||||
nullFallback: left.NullFallback,
|
||||
subQuery: left.MultiMatchSubQuery,
|
||||
op: op,
|
||||
otherOperand: right,
|
||||
@@ -227,7 +227,7 @@ func buildResolversExpr(
|
||||
expr = dbx.Enclose(dbx.And(expr, mm))
|
||||
} else if right.MultiMatchSubQuery != nil {
|
||||
mm := &manyVsOneExpr{
|
||||
noCoalesce: right.NoCoalesce,
|
||||
nullFallback: right.NullFallback,
|
||||
subQuery: right.MultiMatchSubQuery,
|
||||
op: op,
|
||||
otherOperand: left,
|
||||
@@ -326,9 +326,6 @@ func resolveToken(token fexpr.Token, fieldResolver FieldResolver) (*ResolverResu
|
||||
// `COALESCE(a, "") = ""` since the direct match can be accomplished
|
||||
// with a seek while the COALESCE will induce a table scan.
|
||||
func resolveEqualExpr(equal bool, left, right *ResolverResult) dbx.Expression {
|
||||
isLeftEmpty := isEmptyIdentifier(left) || (len(left.Params) == 1 && hasEmptyParamValue(left))
|
||||
isRightEmpty := isEmptyIdentifier(right) || (len(right.Params) == 1 && hasEmptyParamValue(right))
|
||||
|
||||
equalOp := "="
|
||||
nullEqualOp := "IS"
|
||||
concatOp := "OR"
|
||||
@@ -343,16 +340,23 @@ func resolveEqualExpr(equal bool, left, right *ResolverResult) dbx.Expression {
|
||||
nullExpr = "IS NOT NULL"
|
||||
}
|
||||
|
||||
// no coalesce (eg. compare to a json field)
|
||||
// no coalesce fallback (eg. compare to a json field)
|
||||
// a IS b
|
||||
// a IS NOT b
|
||||
if left.NoCoalesce || right.NoCoalesce {
|
||||
if left.NullFallback == NullFallbackDisabled ||
|
||||
right.NullFallback == NullFallbackDisabled {
|
||||
return dbx.NewExp(
|
||||
fmt.Sprintf("%s %s %s", left.Identifier, nullEqualOp, right.Identifier),
|
||||
mergeParams(left.Params, right.Params),
|
||||
)
|
||||
}
|
||||
|
||||
isLeftEmpty := isEmptyIdentifier(left) ||
|
||||
(left.NullFallback == NullFallbackAuto && len(left.Params) == 1 && hasEmptyParamValue(left))
|
||||
|
||||
isRightEmpty := isEmptyIdentifier(right) ||
|
||||
(right.NullFallback == NullFallbackAuto && len(right.Params) == 1 && hasEmptyParamValue(right))
|
||||
|
||||
// both operands are empty
|
||||
if isLeftEmpty && isRightEmpty {
|
||||
return dbx.NewExp(fmt.Sprintf("'' %s ''", equalOp), mergeParams(left.Params, right.Params))
|
||||
@@ -421,6 +425,10 @@ func hasEmptyParamValue(result *ResolverResult) bool {
|
||||
}
|
||||
|
||||
func isKnownNonEmptyIdentifier(result *ResolverResult) bool {
|
||||
if result.NullFallback == NullFallbackEnforced {
|
||||
return false
|
||||
}
|
||||
|
||||
switch strings.ToLower(result.Identifier) {
|
||||
case "1", "0", "false", `true`:
|
||||
return true
|
||||
@@ -631,13 +639,13 @@ func (e *manyVsManyExpr) Build(db *dbx.DB, params dbx.Params) string {
|
||||
|
||||
whereExpr, buildErr := buildResolversExpr(
|
||||
&ResolverResult{
|
||||
NoCoalesce: e.left.NoCoalesce,
|
||||
Identifier: "[[" + lAlias + ".multiMatchValue]]",
|
||||
NullFallback: e.left.NullFallback,
|
||||
Identifier: "[[" + lAlias + ".multiMatchValue]]",
|
||||
},
|
||||
e.op,
|
||||
&ResolverResult{
|
||||
NoCoalesce: e.right.NoCoalesce,
|
||||
Identifier: "[[" + rAlias + ".multiMatchValue]]",
|
||||
NullFallback: e.right.NullFallback,
|
||||
Identifier: "[[" + rAlias + ".multiMatchValue]]",
|
||||
// note: the AfterBuild needs to be handled only once and it
|
||||
// doesn't matter whether it is applied on the left or right subquery operand
|
||||
AfterBuild: dbx.Not, // inverse for the not-exist expression
|
||||
@@ -672,7 +680,7 @@ type manyVsOneExpr struct {
|
||||
subQuery dbx.Expression
|
||||
op fexpr.SignOp
|
||||
inverse bool
|
||||
noCoalesce bool
|
||||
nullFallback NullFallbackPreference
|
||||
}
|
||||
|
||||
// Build converts the expression into a SQL fragment.
|
||||
@@ -686,9 +694,9 @@ func (e *manyVsOneExpr) Build(db *dbx.DB, params dbx.Params) string {
|
||||
alias := "__sm" + security.PseudorandomString(8)
|
||||
|
||||
r1 := &ResolverResult{
|
||||
NoCoalesce: e.noCoalesce,
|
||||
Identifier: "[[" + alias + ".multiMatchValue]]",
|
||||
AfterBuild: dbx.Not, // inverse for the not-exist expression
|
||||
NullFallback: e.nullFallback,
|
||||
Identifier: "[[" + alias + ".multiMatchValue]]",
|
||||
AfterBuild: dbx.Not, // inverse for the not-exist expression
|
||||
}
|
||||
|
||||
r2 := &ResolverResult{
|
||||
|
||||
Reference in New Issue
Block a user