MCPcopy Create free account
hub / github.com/dolthub/doltgresql / Eval

Method Eval

server/expression/in_subquery.go:63–126  ·  view source on GitHub ↗

Eval implements the sql.Expression interface.

(ctx *sql.Context, row sql.Row)

Source from the content-addressed store, hash-verified

61
62// Eval implements the sql.Expression interface.
63func (in *InSubquery) Eval(ctx *sql.Context, row sql.Row) (any, error) {
64 if len(in.compFuncs) == 0 {
65 return nil, errors.Errorf("%T: cannot Eval as it has not been fully resolved", in)
66 }
67
68 left, err := in.leftExpr.Eval(ctx, row)
69 if err != nil {
70 return nil, err
71 }
72
73 // The NULL handling for IN expressions is tricky. According to
74 // https://www.postgresql.org/docs/16/functions-comparisons.html#FUNCTIONS-COMPARISONS-IN-SCALAR:
75 // To comply with the SQL standard, IN() returns NULL not only if the expression on the left hand side is NULL, but
76 // also if no match is found in the list and one of the expressions in the list is NULL.
77 leftNull := left == nil
78
79 if types.NumColumns(in.Left().Type(ctx)) != types.NumColumns(in.Right().Type(ctx)) {
80 return nil, sql.ErrInvalidOperandColumns.New(types.NumColumns(in.Left().Type(ctx)), types.NumColumns(in.Right().Type(ctx)))
81 }
82
83 right := in.rightExpr
84
85 // TODO: does this work for all pg values?
86 values, err := right.HashMultiple(ctx, row)
87 if err != nil {
88 return nil, err
89 }
90
91 // NULL IN (list) returns NULL. NULL IN (empty list) returns 0
92 if leftNull {
93 if values.Size() == 0 {
94 return false, nil
95 }
96 return nil, nil
97 }
98
99 // TODO: it might be possible for the left value to hash to a different value than the right even though they pass
100 // an equality check. We need to perform a type conversion here to catch this case.
101 key, err := hash.HashOf(ctx, nil, sql.NewRow(left))
102 if err != nil {
103 return nil, err
104 }
105
106 // If the hashed values don't contain the left value hash, we know it's not there.
107 // If we do find the hash of the left value, we still need to check for equality,
108 // since non-equal values could have the same hash in some cases.
109 val, notFoundErr := values.Get(key)
110 if notFoundErr != nil {
111 if _, nilValNotFoundErr := values.Get(nilKey); nilValNotFoundErr == nil {
112 return nil, nil
113 }
114 return false, nil
115 }
116
117 var r sql.Row
118 rowVal, ok := val.([]any)
119 if !ok {
120 r = sql.Row{val}

Callers

nothing calls this directly

Calls 9

LeftMethod · 0.95
RightMethod · 0.95
valuesEqualMethod · 0.95
ErrorfMethod · 0.65
EvalMethod · 0.65
TypeMethod · 0.65
SizeMethod · 0.65
HashOfMethod · 0.45
GetMethod · 0.45

Tested by

no test coverage detected