(typ *types.T)
| 2359 | } |
| 2360 | |
| 2361 | func makeEvalTupleIn(typ *types.T) *CmpOp { |
| 2362 | return &CmpOp{ |
| 2363 | LeftType: typ, |
| 2364 | RightType: types.AnyTuple, |
| 2365 | Fn: func(ctx *EvalContext, arg, values Datum) (Datum, error) { |
| 2366 | vtuple := values.(*DTuple) |
| 2367 | // If the tuple was sorted during normalization, we can perform an |
| 2368 | // efficient binary search to find if the arg is in the tuple (as |
| 2369 | // long as the arg doesn't contain any NULLs). |
| 2370 | if len(vtuple.D) == 0 { |
| 2371 | // If the rhs tuple is empty, the result is always false (even if arg is |
| 2372 | // or contains NULL). |
| 2373 | return DBoolFalse, nil |
| 2374 | } |
| 2375 | if arg == DNull { |
| 2376 | return DNull, nil |
| 2377 | } |
| 2378 | argTuple, argIsTuple := arg.(*DTuple) |
| 2379 | if vtuple.Sorted() && !(argIsTuple && argTuple.ContainsNull()) { |
| 2380 | // The right-hand tuple is already sorted and contains no NULLs, and the |
| 2381 | // left side is not NULL (e.g. `NULL IN (1, 2)`) or a tuple that |
| 2382 | // contains NULL (e.g. `(1, NULL) IN ((1, 2), (3, 4))`). |
| 2383 | // |
| 2384 | // We can use binary search to make a determination in this case. This |
| 2385 | // is the common case when tuples don't contain NULLs. |
| 2386 | _, result := vtuple.SearchSorted(ctx, arg) |
| 2387 | return MakeDBool(DBool(result)), nil |
| 2388 | } |
| 2389 | |
| 2390 | sawNull := false |
| 2391 | if !argIsTuple { |
| 2392 | // The left-hand side is not a tuple, e.g. `1 IN (1, 2)`. |
| 2393 | for _, val := range vtuple.D { |
| 2394 | if val == DNull { |
| 2395 | sawNull = true |
| 2396 | } else if val.Compare(ctx, arg) == 0 { |
| 2397 | return DBoolTrue, nil |
| 2398 | } |
| 2399 | } |
| 2400 | } else { |
| 2401 | // The left-hand side is a tuple, e.g. `(1, 2) IN ((1, 2), (3, 4))`. |
| 2402 | for _, val := range vtuple.D { |
| 2403 | if val == DNull { |
| 2404 | // We allow for a null value to be in the list of tuples, so we |
| 2405 | // need to check that upfront. |
| 2406 | sawNull = true |
| 2407 | } else { |
| 2408 | // Use the EQ function which properly handles NULLs. |
| 2409 | if res := cmpOpTupleFn(ctx, *argTuple, *val.(*DTuple), EQ); res == DNull { |
| 2410 | sawNull = true |
| 2411 | } else if res == DBoolTrue { |
| 2412 | return DBoolTrue, nil |
| 2413 | } |
| 2414 | } |
| 2415 | } |
| 2416 | } |
| 2417 | if sawNull { |
| 2418 | return DNull, nil |
no test coverage detected
searching dependent graphs…