Implement support for RECORD[] where we support RECORD

Support for ARRAY[] expressions is limited to having a consistent shape,
eg ARRAY[(int,text),(int,text)] as opposed to ARRAY[(int,text),(float,text)] or ARRAY[(int,text),(int,text,float)]
pull/3211/head
Philip Dubé 2019-11-20 23:42:50 +00:00
parent 2268a9cae6
commit 168e11cc9b
5 changed files with 89 additions and 10 deletions

View File

@ -1169,7 +1169,7 @@ FinalizeRouterPlan(PlannedStmt *localPlan, CustomScan *customScan)
/* build target entry pointing to remote scan range table entry */
Var *newVar = makeVarFromTargetEntry(customScanRangeTableIndex, targetEntry);
if (newVar->vartype == RECORDOID)
if (newVar->vartype == RECORDOID || newVar->vartype == RECORDARRAYOID)
{
/*
* Add the anonymous composite type to the type cache and store
@ -1263,7 +1263,7 @@ BlessRecordExpression(Expr *expr)
Oid rowArgTypeId = exprType(rowArg);
int rowArgTypeMod = exprTypmod(rowArg);
if (rowArgTypeId == RECORDOID)
if (rowArgTypeId == RECORDOID || rowArgTypeId == RECORDARRAYOID)
{
/* ensure nested rows are blessed as well */
rowArgTypeMod = BlessRecordExpression((Expr *) rowArg);
@ -1281,6 +1281,33 @@ BlessRecordExpression(Expr *expr)
typeMod = rowTupleDesc->tdtypmod;
}
else if (IsA(expr, ArrayExpr))
{
/*
* Handle row array expressions, e.g. SELECT ARRAY[(1,2)];
*/
ArrayExpr *arrayExpr = (ArrayExpr *) expr;
ListCell *elemCell = NULL;
foreach(elemCell, arrayExpr->elements)
{
Node *elemArg = (Node *) lfirst(elemCell);
int32 arrayTypeMod = BlessRecordExpression((Expr *) elemArg);
/*
* Postgres allows ARRAY[(1,2),(1,2,3)]. We do not.
* If multiple RECORD shapes exist in an ArrayExpr, bail out.
*/
if (typeMod == -1)
{
typeMod = arrayTypeMod;
}
else if (arrayTypeMod != typeMod)
{
return -1;
}
}
}
return typeMod;
}

View File

@ -1402,7 +1402,7 @@ MasterExtendedOpNode(MultiExtendedOp *originalOpNode,
column->varoattno = walkerContext->columnId;
walkerContext->columnId++;
if (column->vartype == RECORDOID)
if (column->vartype == RECORDOID || column->vartype == RECORDARRAYOID)
{
column->vartypmod = BlessRecordExpression(originalTargetEntry->expr);
}

View File

@ -110,7 +110,7 @@ MasterTargetList(List *workerTargetList)
masterColumn->varoattno = columnId;
columnId++;
if (masterColumn->vartype == RECORDOID)
if (masterColumn->vartype == RECORDOID || masterColumn->vartype == RECORDARRAYOID)
{
masterColumn->vartypmod = BlessRecordExpression(workerTargetEntry->expr);
}

View File

@ -11,7 +11,7 @@ SELECT create_distributed_table('test','x');
CREATE OR REPLACE FUNCTION table_returner(INT) RETURNS TABLE(name text, id INT)
AS $$
BEGIN
RETURN QUERY SELECT $1::text, $1;
RETURN QUERY SELECT $1::text, $1;
END;
$$ language plpgsql;
SELECT create_distributed_function('table_returner(int)');
@ -24,8 +24,8 @@ CREATE OR REPLACE FUNCTION record_returner(INOUT id int, OUT name text)
RETURNS record
AS $$
BEGIN
id := id + 1;
name := 'returned';
id := id + 1;
name := 'returned';
END;
$$ language plpgsql;
SELECT create_distributed_function('record_returner(int)');
@ -54,6 +54,24 @@ SELECT (x,y) FROM test GROUP BY x, y ORDER BY x, y;
(2,3)
(4 rows)
SELECT ARRAY[(x,(y,x)),(y,(x,y))] FROM test ORDER BY x, y;
array
-----------------------------------
{"(1,\"(2,1)\")","(2,\"(1,2)\")"}
{"(1,\"(3,1)\")","(3,\"(1,3)\")"}
{"(2,\"(2,2)\")","(2,\"(2,2)\")"}
{"(2,\"(3,2)\")","(3,\"(2,3)\")"}
(4 rows)
SELECT ARRAY[[(x,(y,x))],[(x,(x,y))]] FROM test ORDER BY x, y;
array
---------------------------------------
{{"(1,\"(2,1)\")"},{"(1,\"(1,2)\")"}}
{{"(1,\"(3,1)\")"},{"(1,\"(1,3)\")"}}
{{"(2,\"(2,2)\")"},{"(2,\"(2,2)\")"}}
{{"(2,\"(3,2)\")"},{"(2,\"(2,3)\")"}}
(4 rows)
select distinct (x,y) AS foo, x, y FROM test ORDER BY x, y;
foo | x | y
-------+---+---
@ -81,6 +99,11 @@ SELECT record_returner(x) FROM test ORDER BY x, y;
(3,returned)
(4 rows)
-- RECORD[] with varying shape unsupported
SELECT ARRAY[(x,(y,x),y),(y,(x,y))] FROM test ORDER BY x, y;
ERROR: input of anonymous composite types is not implemented
SELECT ARRAY[[(x,(y,x))],[((x,x),y)]] FROM test ORDER BY x, y;
ERROR: input of anonymous composite types is not implemented
-- router queries support row types
SELECT (x,y) FROM test WHERE x = 1 ORDER BY x, y;
row
@ -96,6 +119,20 @@ SELECT (x,y) AS foo FROM test WHERE x = 1 ORDER BY x, y;
(1,3)
(2 rows)
SELECT ARRAY[(x,(y,x)),(y,(x,y))] FROM test WHERE x = 1 ORDER BY x, y;
array
-----------------------------------
{"(1,\"(2,1)\")","(2,\"(1,2)\")"}
{"(1,\"(3,1)\")","(3,\"(1,3)\")"}
(2 rows)
SELECT ARRAY[[(x,(y,x))],[(x,(x,y))]] FROM test WHERE x = 1 ORDER BY x, y;
array
---------------------------------------
{{"(1,\"(2,1)\")"},{"(1,\"(1,2)\")"}}
{{"(1,\"(3,1)\")"},{"(1,\"(1,3)\")"}}
(2 rows)
select distinct (x,y) AS foo, x, y FROM test WHERE x = 1 ORDER BY x, y;
foo | x | y
-------+---+---
@ -117,6 +154,11 @@ SELECT record_returner(x) FROM test WHERE x = 1 ORDER BY x, y;
(2,returned)
(2 rows)
-- RECORD[] with varying shape unsupported
SELECT ARRAY[(x,(y,x),y),(y,(x,y))] FROM test WHERE x = 1 ORDER BY x, y;
ERROR: input of anonymous composite types is not implemented
SELECT ARRAY[[(x,(y,x))],[((x,x),y)]] FROM test WHERE x = 1 ORDER BY x, y;
ERROR: input of anonymous composite types is not implemented
-- nested row expressions
SELECT (x,(x,y)) AS foo FROM test WHERE x = 1 ORDER BY x, y;
foo

View File

@ -8,7 +8,7 @@ SELECT create_distributed_table('test','x');
CREATE OR REPLACE FUNCTION table_returner(INT) RETURNS TABLE(name text, id INT)
AS $$
BEGIN
RETURN QUERY SELECT $1::text, $1;
RETURN QUERY SELECT $1::text, $1;
END;
$$ language plpgsql;
SELECT create_distributed_function('table_returner(int)');
@ -17,8 +17,8 @@ CREATE OR REPLACE FUNCTION record_returner(INOUT id int, OUT name text)
RETURNS record
AS $$
BEGIN
id := id + 1;
name := 'returned';
id := id + 1;
name := 'returned';
END;
$$ language plpgsql;
SELECT create_distributed_function('record_returner(int)');
@ -29,16 +29,26 @@ INSERT INTO test VALUES (1,2), (1,3), (2,2), (2,3);
-- multi-shard queries support row types
SELECT (x,y) FROM test ORDER BY x, y;
SELECT (x,y) FROM test GROUP BY x, y ORDER BY x, y;
SELECT ARRAY[(x,(y,x)),(y,(x,y))] FROM test ORDER BY x, y;
SELECT ARRAY[[(x,(y,x))],[(x,(x,y))]] FROM test ORDER BY x, y;
select distinct (x,y) AS foo, x, y FROM test ORDER BY x, y;
SELECT table_returner(x) FROM test ORDER BY x, y;
SELECT record_returner(x) FROM test ORDER BY x, y;
-- RECORD[] with varying shape unsupported
SELECT ARRAY[(x,(y,x),y),(y,(x,y))] FROM test ORDER BY x, y;
SELECT ARRAY[[(x,(y,x))],[((x,x),y)]] FROM test ORDER BY x, y;
-- router queries support row types
SELECT (x,y) FROM test WHERE x = 1 ORDER BY x, y;
SELECT (x,y) AS foo FROM test WHERE x = 1 ORDER BY x, y;
SELECT ARRAY[(x,(y,x)),(y,(x,y))] FROM test WHERE x = 1 ORDER BY x, y;
SELECT ARRAY[[(x,(y,x))],[(x,(x,y))]] FROM test WHERE x = 1 ORDER BY x, y;
select distinct (x,y) AS foo, x, y FROM test WHERE x = 1 ORDER BY x, y;
SELECT table_returner(x) FROM test WHERE x = 1 ORDER BY x, y;
SELECT record_returner(x) FROM test WHERE x = 1 ORDER BY x, y;
-- RECORD[] with varying shape unsupported
SELECT ARRAY[(x,(y,x),y),(y,(x,y))] FROM test WHERE x = 1 ORDER BY x, y;
SELECT ARRAY[[(x,(y,x))],[((x,x),y)]] FROM test WHERE x = 1 ORDER BY x, y;
-- nested row expressions
SELECT (x,(x,y)) AS foo FROM test WHERE x = 1 ORDER BY x, y;