Merge pull request #3211 from citusdata/support-recordarray

Implement support for RECORD[] where we support RECORD
pull/3237/head
Philip Dubé 2019-11-27 15:27:13 +00:00 committed by GitHub
commit 6d14f63f81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 */ /* build target entry pointing to remote scan range table entry */
Var *newVar = makeVarFromTargetEntry(customScanRangeTableIndex, targetEntry); 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 * Add the anonymous composite type to the type cache and store
@ -1263,7 +1263,7 @@ BlessRecordExpression(Expr *expr)
Oid rowArgTypeId = exprType(rowArg); Oid rowArgTypeId = exprType(rowArg);
int rowArgTypeMod = exprTypmod(rowArg); int rowArgTypeMod = exprTypmod(rowArg);
if (rowArgTypeId == RECORDOID) if (rowArgTypeId == RECORDOID || rowArgTypeId == RECORDARRAYOID)
{ {
/* ensure nested rows are blessed as well */ /* ensure nested rows are blessed as well */
rowArgTypeMod = BlessRecordExpression((Expr *) rowArg); rowArgTypeMod = BlessRecordExpression((Expr *) rowArg);
@ -1281,6 +1281,33 @@ BlessRecordExpression(Expr *expr)
typeMod = rowTupleDesc->tdtypmod; 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; return typeMod;
} }

View File

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

View File

@ -110,7 +110,7 @@ MasterTargetList(List *workerTargetList)
masterColumn->varoattno = columnId; masterColumn->varoattno = columnId;
columnId++; columnId++;
if (masterColumn->vartype == RECORDOID) if (masterColumn->vartype == RECORDOID || masterColumn->vartype == RECORDARRAYOID)
{ {
masterColumn->vartypmod = BlessRecordExpression(workerTargetEntry->expr); 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) CREATE OR REPLACE FUNCTION table_returner(INT) RETURNS TABLE(name text, id INT)
AS $$ AS $$
BEGIN BEGIN
RETURN QUERY SELECT $1::text, $1; RETURN QUERY SELECT $1::text, $1;
END; END;
$$ language plpgsql; $$ language plpgsql;
SELECT create_distributed_function('table_returner(int)'); 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 RETURNS record
AS $$ AS $$
BEGIN BEGIN
id := id + 1; id := id + 1;
name := 'returned'; name := 'returned';
END; END;
$$ language plpgsql; $$ language plpgsql;
SELECT create_distributed_function('record_returner(int)'); 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) (2,3)
(4 rows) (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; select distinct (x,y) AS foo, x, y FROM test ORDER BY x, y;
foo | x | y foo | x | y
-------+---+--- -------+---+---
@ -81,6 +99,11 @@ SELECT record_returner(x) FROM test ORDER BY x, y;
(3,returned) (3,returned)
(4 rows) (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 -- router queries support row types
SELECT (x,y) FROM test WHERE x = 1 ORDER BY x, y; SELECT (x,y) FROM test WHERE x = 1 ORDER BY x, y;
row row
@ -96,6 +119,20 @@ SELECT (x,y) AS foo FROM test WHERE x = 1 ORDER BY x, y;
(1,3) (1,3)
(2 rows) (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; select distinct (x,y) AS foo, x, y FROM test WHERE x = 1 ORDER BY x, y;
foo | 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,returned)
(2 rows) (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 -- nested row expressions
SELECT (x,(x,y)) AS foo FROM test WHERE x = 1 ORDER BY x, y; SELECT (x,(x,y)) AS foo FROM test WHERE x = 1 ORDER BY x, y;
foo 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) CREATE OR REPLACE FUNCTION table_returner(INT) RETURNS TABLE(name text, id INT)
AS $$ AS $$
BEGIN BEGIN
RETURN QUERY SELECT $1::text, $1; RETURN QUERY SELECT $1::text, $1;
END; END;
$$ language plpgsql; $$ language plpgsql;
SELECT create_distributed_function('table_returner(int)'); 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 RETURNS record
AS $$ AS $$
BEGIN BEGIN
id := id + 1; id := id + 1;
name := 'returned'; name := 'returned';
END; END;
$$ language plpgsql; $$ language plpgsql;
SELECT create_distributed_function('record_returner(int)'); 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 -- multi-shard queries support row types
SELECT (x,y) FROM test ORDER BY x, y; SELECT (x,y) FROM test ORDER BY x, y;
SELECT (x,y) FROM test GROUP BY x, y 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 distinct (x,y) AS foo, x, y FROM test ORDER BY x, y;
SELECT table_returner(x) 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; 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 -- router queries support row types
SELECT (x,y) FROM test WHERE x = 1 ORDER BY x, y; 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 (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 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 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; 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 -- nested row expressions
SELECT (x,(x,y)) AS foo FROM test WHERE x = 1 ORDER BY x, y; SELECT (x,(x,y)) AS foo FROM test WHERE x = 1 ORDER BY x, y;