Skip to content

Commit

Permalink
tree: add REFCURSOR to the list of parsable string types
Browse files Browse the repository at this point in the history
This patch adds the new `REFCURSOR` data type to the list of types that
a string constant can have. This will allow constant values to avoid
an explicit cast to `REFCURSOR` in cases when the context expects a
`REFCURSOR`, e.g. inserting into a `REFCURSOR` column or calling a
routine with a `REFCURSOR` parameter. Example:
```
CREATE FUNCTION f(curs REFCURSOR) RETURNS REFCURSOR AS $$
  SELECT curs;
$$ LANGUAGE SQL;

-- This cast was necessary before:
SELECT f('foo'::REFCURSOR);

-- Now this works:
SELECT f('foo');
```

Informs cockroachdb#111560

Release note: None
  • Loading branch information
DrewKimball committed Oct 6, 2023
1 parent 0e4e2f4 commit 6865e69
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 43 deletions.
10 changes: 5 additions & 5 deletions pkg/sql/logictest/testdata/logic_test/refcursor
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ statement ok
ALTER TABLE xy ADD COLUMN curs REFCURSOR;

statement ok
INSERT INTO xy VALUES (1, 2, 'foo'::REFCURSOR);
INSERT INTO xy VALUES (1, 2, 'foo');

query IIT
SELECT * FROM xy;
Expand All @@ -45,7 +45,7 @@ statement ok
ALTER TABLE xy ALTER COLUMN y TYPE REFCURSOR;

statement ok
INSERT INTO xy VALUES (1, 'bar'::REFCURSOR);
INSERT INTO xy VALUES (1, 'bar');

query IT
SELECT * FROM xy;
Expand Down Expand Up @@ -77,7 +77,7 @@ statement ok
CREATE TYPE typ AS (x INT, y REFCURSOR);

query T
SELECT (100, 'bar'::REFCURSOR)::typ;
SELECT (100, 'bar')::typ;
----
(100,bar)

Expand Down Expand Up @@ -119,7 +119,7 @@ CREATE FUNCTION f(curs REFCURSOR) RETURNS INT AS $$
$$ LANGUAGE SQL;

query I
SELECT f('foo'::REFCURSOR);
SELECT f('foo');
----
0

Expand All @@ -134,7 +134,7 @@ CREATE FUNCTION f(curs REFCURSOR) RETURNS INT AS $$
$$ LANGUAGE PLpgSQL;

query I
SELECT f('foo'::REFCURSOR);
SELECT f('foo');
----
0

Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/sem/tree/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,8 @@ var (
types.Jsonb,
types.PGLSN,
types.PGLSNArray,
types.RefCursor,
types.RefCursorArray,
types.TSQuery,
types.TSVector,
types.VarBit,
Expand Down
107 changes: 69 additions & 38 deletions pkg/sql/sem/tree/constant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ func mustParseDPGLSN(t *testing.T, s string) tree.Datum {
}
return d
}
func mustParseDRefCursor(_ *testing.T, s string) tree.Datum {
return tree.NewDRefCursor(s)
}
func mustParseDINet(t *testing.T, s string) tree.Datum {
d, err := tree.ParseDIPAddrFromINetString(s)
if err != nil {
Expand Down Expand Up @@ -406,6 +409,7 @@ var parseFuncs = map[*types.T]func(*testing.T, string) tree.Datum{
types.INet: mustParseDINet,
types.VarBit: mustParseDVarBit,
types.PGLSN: mustParseDPGLSN,
types.RefCursor: mustParseDRefCursor,
types.TSQuery: mustParseDTSQuery,
types.TSVector: mustParseDTSVector,
types.BytesArray: mustParseDArrayOfType(types.Bytes),
Expand All @@ -417,14 +421,14 @@ var parseFuncs = map[*types.T]func(*testing.T, string) tree.Datum{
types.UUIDArray: mustParseDArrayOfType(types.Uuid),
types.DateArray: mustParseDArrayOfType(types.Date),
types.PGLSNArray: mustParseDArrayOfType(types.PGLSN),
types.RefCursorArray: mustParseDArrayOfType(types.RefCursor),
types.TimeArray: mustParseDArrayOfType(types.Time),
types.TimeTZArray: mustParseDArrayOfType(types.TimeTZ),
types.TimestampArray: mustParseDArrayOfType(types.Timestamp),
types.TimestampTZArray: mustParseDArrayOfType(types.TimestampTZ),
types.IntervalArray: mustParseDArrayOfType(types.Interval),
types.INetArray: mustParseDArrayOfType(types.INet),
types.VarBitArray: mustParseDArrayOfType(types.VarBit),
types.PGLSNArray: mustParseDArrayOfType(types.PGLSN),
}

func typeSet(tys ...*types.T) map[*types.T]struct{} {
Expand All @@ -449,27 +453,32 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
}{
{
c: tree.NewStrVal("abc 世界"),
parseOptions: typeSet(types.String, types.Bytes, types.TSVector),
parseOptions: typeSet(types.String, types.Bytes, types.TSVector, types.RefCursor),
},
{
c: tree.NewStrVal("true"),
parseOptions: typeSet(types.String, types.Bytes, types.Bool, types.Jsonb, types.TSVector, types.TSQuery),
c: tree.NewStrVal("true"),
parseOptions: typeSet(types.String, types.Bytes, types.Bool, types.Jsonb, types.TSVector,
types.TSQuery, types.RefCursor),
},
{
c: tree.NewStrVal("2010-09-28"),
parseOptions: typeSet(types.String, types.Bytes, types.Date, types.Timestamp, types.TimestampTZ, types.TSVector, types.TSQuery),
c: tree.NewStrVal("2010-09-28"),
parseOptions: typeSet(types.String, types.Bytes, types.Date, types.Timestamp,
types.TimestampTZ, types.TSVector, types.TSQuery, types.RefCursor),
},
{
c: tree.NewStrVal("2010-09-28 12:00:00.1"),
parseOptions: typeSet(types.String, types.Bytes, types.Time, types.TimeTZ, types.Timestamp, types.TimestampTZ, types.Date),
c: tree.NewStrVal("2010-09-28 12:00:00.1"),
parseOptions: typeSet(types.String, types.Bytes, types.Time, types.TimeTZ, types.Timestamp,
types.TimestampTZ, types.Date, types.RefCursor),
},
{
c: tree.NewStrVal("2006-07-08T00:00:00.000000123Z"),
parseOptions: typeSet(types.String, types.Bytes, types.Time, types.TimeTZ, types.Timestamp, types.TimestampTZ, types.Date),
c: tree.NewStrVal("2006-07-08T00:00:00.000000123Z"),
parseOptions: typeSet(types.String, types.Bytes, types.Time, types.TimeTZ, types.Timestamp,
types.TimestampTZ, types.Date, types.RefCursor),
},
{
c: tree.NewStrVal("PT12H2M"),
parseOptions: typeSet(types.String, types.Bytes, types.Interval, types.TSVector, types.TSQuery),
c: tree.NewStrVal("PT12H2M"),
parseOptions: typeSet(types.String, types.Bytes, types.Interval, types.TSVector,
types.TSQuery, types.RefCursor),
},
{
c: tree.NewBytesStrVal("abc 世界"),
Expand All @@ -492,16 +501,19 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
parseOptions: typeSet(types.String, types.Bytes),
},
{
c: tree.NewStrVal("box(0 0, 1 1)"),
parseOptions: typeSet(types.String, types.Bytes, types.Box2D, types.TSVector),
c: tree.NewStrVal("box(0 0, 1 1)"),
parseOptions: typeSet(types.String, types.Bytes, types.Box2D, types.TSVector,
types.RefCursor),
},
{
c: tree.NewStrVal("POINT(-100.59 42.94)"),
parseOptions: typeSet(types.String, types.Bytes, types.Geography, types.Geometry, types.TSVector),
c: tree.NewStrVal("POINT(-100.59 42.94)"),
parseOptions: typeSet(types.String, types.Bytes, types.Geography, types.Geometry,
types.TSVector, types.RefCursor),
},
{
c: tree.NewStrVal("192.168.100.128/25"),
parseOptions: typeSet(types.String, types.Bytes, types.INet, types.TSVector, types.TSQuery),
c: tree.NewStrVal("192.168.100.128/25"),
parseOptions: typeSet(types.String, types.Bytes, types.INet, types.TSVector, types.TSQuery,
types.RefCursor),
},
{
c: tree.NewStrVal("111000110101"),
Expand All @@ -516,15 +528,17 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
types.Jsonb,
types.TSVector,
types.TSQuery,
types.RefCursor,
),
},
{
c: tree.NewStrVal("A/1"),
parseOptions: typeSet(types.String, types.PGLSN, types.Bytes, types.TSQuery, types.TSVector),
c: tree.NewStrVal("A/1"),
parseOptions: typeSet(types.String, types.PGLSN, types.Bytes, types.TSQuery, types.TSVector,
types.RefCursor),
},
{
c: tree.NewStrVal(`{"a": 1}`),
parseOptions: typeSet(types.String, types.Bytes, types.Jsonb),
parseOptions: typeSet(types.String, types.Bytes, types.Jsonb, types.RefCursor),
},
{
c: tree.NewStrVal(`{1,2}`),
Expand All @@ -539,6 +553,8 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
types.IntervalArray,
types.TSVector,
types.TSQuery,
types.RefCursor,
types.RefCursorArray,
),
},
{
Expand All @@ -553,37 +569,44 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
types.IntervalArray,
types.TSVector,
types.TSQuery,
types.RefCursor,
types.RefCursorArray,
),
},
{
c: tree.NewStrVal(`{a,b}`),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray, types.TSVector, types.TSQuery),
c: tree.NewStrVal(`{a,b}`),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray,
types.TSVector, types.TSQuery, types.RefCursor, types.RefCursorArray),
},
{
c: tree.NewBytesStrVal(string([]byte{0xff, 0xfe, 0xfd})),
parseOptions: typeSet(types.String, types.Bytes),
},
{
c: tree.NewStrVal(`18e7b17e-4ead-4e27-bfd5-bb6d11261bb6`),
parseOptions: typeSet(types.String, types.Bytes, types.Uuid, types.TSVector, types.TSQuery),
c: tree.NewStrVal(`18e7b17e-4ead-4e27-bfd5-bb6d11261bb6`),
parseOptions: typeSet(types.String, types.Bytes, types.Uuid, types.TSVector, types.TSQuery,
types.RefCursor),
},
{
c: tree.NewStrVal(`{18e7b17e-4ead-4e27-bfd5-bb6d11261bb6, 18e7b17e-4ead-4e27-bfd5-bb6d11261bb7}`),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray, types.UUIDArray, types.TSVector),
c: tree.NewStrVal(`{18e7b17e-4ead-4e27-bfd5-bb6d11261bb6, 18e7b17e-4ead-4e27-bfd5-bb6d11261bb7}`),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray,
types.UUIDArray, types.TSVector, types.RefCursor, types.RefCursorArray),
},
{
c: tree.NewStrVal("{true, false}"),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray, types.BoolArray, types.TSVector),
c: tree.NewStrVal("{true, false}"),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray,
types.BoolArray, types.TSVector, types.RefCursor, types.RefCursorArray),
},
{
c: tree.NewStrVal("{2010-09-28, 2010-09-29}"),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray, types.DateArray,
types.TimestampArray, types.TimestampTZArray, types.TSVector),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray,
types.DateArray, types.TimestampArray, types.TimestampTZArray, types.TSVector,
types.RefCursor, types.RefCursorArray),
},
{
c: tree.NewStrVal("{1A/1,2/2A}"),
parseOptions: typeSet(types.String, types.PGLSNArray, types.Bytes, types.BytesArray,
types.StringArray, types.TSQuery, types.TSVector),
types.StringArray, types.TSQuery, types.TSVector, types.RefCursor, types.RefCursorArray),
},
{
c: tree.NewStrVal("{2010-09-28 12:00:00.1, 2010-09-29 12:00:00.1}"),
Expand All @@ -596,7 +619,9 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
types.TimeTZArray,
types.TimestampArray,
types.TimestampTZArray,
types.DateArray),
types.DateArray,
types.RefCursor,
types.RefCursorArray),
},
{
c: tree.NewStrVal("{2006-07-08T00:00:00.000000123Z, 2006-07-10T00:00:00.000000123Z}"),
Expand All @@ -609,15 +634,19 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
types.TimeTZArray,
types.TimestampArray,
types.TimestampTZArray,
types.DateArray),
types.DateArray,
types.RefCursor,
types.RefCursorArray),
},
{
c: tree.NewStrVal("{PT12H2M, -23:00:00}"),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray, types.IntervalArray),
c: tree.NewStrVal("{PT12H2M, -23:00:00}"),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray,
types.IntervalArray, types.RefCursor, types.RefCursorArray),
},
{
c: tree.NewStrVal("{192.168.100.128, ::ffff:10.4.3.2}"),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray, types.INetArray),
c: tree.NewStrVal("{192.168.100.128, ::ffff:10.4.3.2}"),
parseOptions: typeSet(types.String, types.Bytes, types.BytesArray, types.StringArray,
types.INetArray, types.RefCursor, types.RefCursorArray),
},
{
c: tree.NewStrVal("{0101, 11}"),
Expand All @@ -632,6 +661,8 @@ func TestStringConstantResolveAvailableTypes(t *testing.T) {
types.IntervalArray,
types.VarBitArray,
types.TSVector,
types.RefCursor,
types.RefCursorArray,
),
},
}
Expand Down

0 comments on commit 6865e69

Please sign in to comment.