Skip to content

Commit

Permalink
tree: disallow and test comparison operators for REFCURSOR
Browse files Browse the repository at this point in the history
The `REFCURSOR` data type does not support comparisons apart from a
few edge cases like `'foo'::REFCURSOR IS NULL`. Example:
```
postgres=# SELECT 'foo'::REFCURSOR = 'foo'::REFCURSOR;
ERROR:  operator does not exist: refcursor = refcursor
```
The previous commit that added the `RefCursorFamily` type family already
effectively removed support for most comparisons; this commit also
prevents the `IS / IS DISTINCT FROM` variants from being used on a
`REFCURSOR` expression. Note that postgres supports a few cases with
`NULL` as mentioned above. However, this case seems unimportant, so I
leave it as a TODO for now.

This commit also adds tests for various comparisons involving `REFCURSOR`.

Informs cockroachdb#111560

Release note: None
  • Loading branch information
DrewKimball committed Oct 7, 2023
1 parent 24a2382 commit b8bb90b
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
74 changes: 74 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/refcursor
Original file line number Diff line number Diff line change
Expand Up @@ -391,4 +391,78 @@ NULL a NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL foo NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL foo NULL NULL NULL NULL NULL NULL NULL NULL

# REFCURSOR doesn't support any comparisons (with an exception mentioned below).
subtest comparisons

# TODO(drewk): The error code should be 42883.
statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR = 'foo'::REFCURSOR;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR = 'foo'::TEXT;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR = NULL;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR < 'foo'::REFCURSOR;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR < 'foo'::TEXT;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR < NULL;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR > 'foo'::REFCURSOR;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR > 'foo'::TEXT;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR > NULL;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR <= 'foo'::REFCURSOR;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR <= 'foo'::TEXT;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR <= NULL;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR >= 'foo'::REFCURSOR;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR >= 'foo'::TEXT;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR >= NULL;

# TODO(drewk): Postgres allows this case.
statement error pgcode 42883 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS NULL;

statement error pgcode 42883 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS NOT NULL;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS DISTINCT FROM 'foo'::REFCURSOR;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS DISTINCT FROM 'foo'::TEXT;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS DISTINCT FROM NULL;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS NOT DISTINCT FROM 'foo'::REFCURSOR;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS NOT DISTINCT FROM 'foo'::TEXT;

statement error pgcode 22023 pq: unsupported comparison operator
SELECT 'foo'::REFCURSOR IS NOT DISTINCT FROM NULL;

subtest end
20 changes: 20 additions & 0 deletions pkg/sql/sem/tree/type_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,14 @@ func (expr *ComparisonExpr) TypeCheck(
return nil, err
}

// REFCURSOR does not support comparisons.
leftType, rightType := leftTyped.ResolvedType(), rightTyped.ResolvedType()
if leftType.Family() == types.RefCursorFamily || rightType.Family() == types.RefCursorFamily {
return nil, pgerror.Newf(pgcode.UndefinedFunction,
"unsupported comparison operator: <%s> %s <%s>", leftType, cmpOp, rightType,
)
}

if alwaysNull {
return DNull, nil
}
Expand Down Expand Up @@ -1463,6 +1471,12 @@ func (expr *IsNullExpr) TypeCheck(
if err != nil {
return nil, err
}
// REFCURSOR does not support comparisons.
if exprTyped.ResolvedType().Family() == types.RefCursorFamily {
return nil, pgerror.New(pgcode.UndefinedFunction,
"unsupported comparison operator: refcursor IS unknown",
)
}
expr.Expr = exprTyped
expr.typ = types.Bool
return expr, nil
Expand All @@ -1476,6 +1490,12 @@ func (expr *IsNotNullExpr) TypeCheck(
if err != nil {
return nil, err
}
// REFCURSOR does not support comparisons.
if exprTyped.ResolvedType().Family() == types.RefCursorFamily {
return nil, pgerror.New(pgcode.UndefinedFunction,
"unsupported comparison operator: refcursor IS NOT unknown",
)
}
expr.Expr = exprTyped
expr.typ = types.Bool
return expr, nil
Expand Down

0 comments on commit b8bb90b

Please sign in to comment.