Skip to content

Commit

Permalink
Merge pull request #61658 from RaduBerinde/backport20.2-61574
Browse files Browse the repository at this point in the history
release-20.2: opt: detect invalid tuple comparison with ANY
  • Loading branch information
RaduBerinde authored Mar 9, 2021
2 parents a3a792d + 2778c5c commit 4da6dc3
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
21 changes: 21 additions & 0 deletions pkg/sql/opt/optbuilder/testdata/subquery
Original file line number Diff line number Diff line change
Expand Up @@ -2255,3 +2255,24 @@ build
SELECT 1 FROM (VALUES (1)) AS a(x) HAVING (SELECT true FROM (VALUES (a.x)) AS b(y))
----
error (42803): subquery uses ungrouped column "x" from outer query

build
SELECT ((1, 2), (3, 4)) = ANY (VALUES (('foo', 'bar')))
----
error (22023): unsupported comparison operator: <tuple{tuple{int, int}, tuple{int, int}}> = ANY <tuple{tuple{string, string}}>

# Regression test for #61229 - detect uncomparable tuple types.
build
SELECT (1, 1) = ANY (VALUES ('foo', 'bar'))
----
error (22023): unsupported comparison operator: <tuple{int, int}> = ANY <tuple{tuple{string AS column1, string AS column2}}>

build
SELECT ARRAY[1, 2] = ANY (VALUES (ARRAY['foo', 'bar']))
----
error (22023): unsupported comparison operator: <int[]> = ANY <tuple{string[]}>

build
SELECT (1, 1) = ANY (VALUES (1, 2, 3))
----
error (22023): unsupported comparison operator: <tuple{int, int}> = ANY <tuple{tuple{int AS column1, int AS column2, int AS column3}}>
23 changes: 22 additions & 1 deletion pkg/sql/sem/tree/type_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -1852,12 +1852,33 @@ func typeCheckComparisonOpWithSubOperator(
}
}
fn, ok := ops.LookupImpl(cmpTypeLeft, cmpTypeRight)
if !ok {
if !ok || !deepCheckValidCmpOp(ops, cmpTypeLeft, cmpTypeRight) {
return nil, nil, nil, false, subOpCompError(cmpTypeLeft, rightTyped.ResolvedType(), subOp, op)
}
return leftTyped, rightTyped, fn, false, nil
}

// deepCheckValidCmpOp performs extra checks that a given operation is valid
// when the types are tuples.
func deepCheckValidCmpOp(ops cmpOpOverload, leftType, rightType *types.T) bool {
if leftType.Family() == types.TupleFamily && rightType.Family() == types.TupleFamily {
l := leftType.TupleContents()
r := rightType.TupleContents()
if len(l) != len(r) {
return false
}
for i := range l {
if _, ok := ops.LookupImpl(l[i], r[i]); !ok {
return false
}
if !deepCheckValidCmpOp(ops, l[i], r[i]) {
return false
}
}
}
return true
}

func subOpCompError(leftType, rightType *types.T, subOp, op ComparisonOperator) error {
sig := fmt.Sprintf(compSignatureWithSubOpFmt, leftType, subOp, op, rightType)
return pgerror.Newf(pgcode.InvalidParameterValue, unsupportedCompErrFmt, sig)
Expand Down

0 comments on commit 4da6dc3

Please sign in to comment.