(ctx *EvalContext, left, right DTuple, op ComparisonOperator)
| 2311 | } |
| 2312 | |
| 2313 | func cmpOpTupleFn(ctx *EvalContext, left, right DTuple, op ComparisonOperator) Datum { |
| 2314 | cmp := 0 |
| 2315 | sawNull := false |
| 2316 | for i, leftElem := range left.D { |
| 2317 | rightElem := right.D[i] |
| 2318 | // Like with cmpOpScalarFn, check for values that need to be handled |
| 2319 | // differently than when ordering Datums. |
| 2320 | if leftElem == DNull || rightElem == DNull { |
| 2321 | switch op { |
| 2322 | case EQ: |
| 2323 | // If either Datum is NULL and the op is EQ, we continue the |
| 2324 | // comparison and the result is only NULL if the other (non-NULL) |
| 2325 | // elements are equal. This is because NULL is thought of as "unknown", |
| 2326 | // so a NULL equality comparison does not prevent the equality from |
| 2327 | // being proven false, but does prevent it from being proven true. |
| 2328 | sawNull = true |
| 2329 | |
| 2330 | case IsNotDistinctFrom: |
| 2331 | // For IS NOT DISTINCT FROM, NULLs are "equal". |
| 2332 | if leftElem != DNull || rightElem != DNull { |
| 2333 | return DBoolFalse |
| 2334 | } |
| 2335 | |
| 2336 | default: |
| 2337 | // If either Datum is NULL and the op is not EQ or IS NOT DISTINCT FROM, |
| 2338 | // we short-circuit the evaluation and the result of the comparison is |
| 2339 | // NULL. This is because NULL is thought of as "unknown" and tuple |
| 2340 | // inequality is defined lexicographically, so once a NULL comparison is |
| 2341 | // seen, the result of the entire tuple comparison is unknown. |
| 2342 | return DNull |
| 2343 | } |
| 2344 | } else { |
| 2345 | cmp = leftElem.Compare(ctx, rightElem) |
| 2346 | if cmp != 0 { |
| 2347 | break |
| 2348 | } |
| 2349 | } |
| 2350 | } |
| 2351 | b := boolFromCmp(cmp, op) |
| 2352 | if b == DBoolTrue && sawNull { |
| 2353 | // The op is EQ and all non-NULL elements are equal, but we saw at least |
| 2354 | // one NULL element. Since NULL comparisons are treated as unknown, the |
| 2355 | // result of the comparison becomes unknown (NULL). |
| 2356 | return DNull |
| 2357 | } |
| 2358 | return b |
| 2359 | } |
| 2360 | |
| 2361 | func makeEvalTupleIn(typ *types.T) *CmpOp { |
| 2362 | return &CmpOp{ |
no test coverage detected
searching dependent graphs…