Fix segfault in column_to_column_name (#3260)

Fix segfault in column_to_column_name
pull/3258/head
Marco Slot 2019-12-03 14:30:40 +01:00 committed by GitHub
commit 0b71697d88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 34 deletions

View File

@ -643,7 +643,7 @@ DistributionCreateCommand(DistTableCacheEntry *cacheEntry)
} }
else else
{ {
char *partitionKeyColumnName = ColumnNameToColumn(relationId, partitionKeyString); char *partitionKeyColumnName = ColumnToColumnName(relationId, partitionKeyString);
appendStringInfo(tablePartitionKeyString, "column_name_to_column(%s,%s)", appendStringInfo(tablePartitionKeyString, "column_name_to_column(%s,%s)",
quote_literal_cstr(qualifiedRelationName), quote_literal_cstr(qualifiedRelationName),
quote_literal_cstr(partitionKeyColumnName)); quote_literal_cstr(partitionKeyColumnName));

View File

@ -715,7 +715,7 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
DistTableCacheEntry *cacheEntry = DistributedTableCacheEntry( DistTableCacheEntry *cacheEntry = DistributedTableCacheEntry(
distributedTableId); distributedTableId);
char *partitionKeyString = cacheEntry->partitionKeyString; char *partitionKeyString = cacheEntry->partitionKeyString;
char *partitionColumnName = ColumnNameToColumn(distributedTableId, char *partitionColumnName = ColumnToColumnName(distributedTableId,
partitionKeyString); partitionKeyString);
appendStringInfo(errorHint, "Consider using an equality filter on " appendStringInfo(errorHint, "Consider using an equality filter on "
@ -2556,7 +2556,7 @@ BuildRoutesForInsert(Query *query, DeferredErrorMessage **planningError)
if (prunedShardIntervalCount != 1) if (prunedShardIntervalCount != 1)
{ {
char *partitionKeyString = cacheEntry->partitionKeyString; char *partitionKeyString = cacheEntry->partitionKeyString;
char *partitionColumnName = ColumnNameToColumn(distributedTableId, char *partitionColumnName = ColumnToColumnName(distributedTableId,
partitionKeyString); partitionKeyString);
StringInfo errorMessage = makeStringInfo(); StringInfo errorMessage = makeStringInfo();
StringInfo errorHint = makeStringInfo(); StringInfo errorHint = makeStringInfo();

View File

@ -105,7 +105,7 @@ column_to_column_name(PG_FUNCTION_ARGS)
CheckCitusVersion(ERROR); CheckCitusVersion(ERROR);
char *columnName = ColumnNameToColumn(relationId, columnNodeString); char *columnName = ColumnToColumnName(relationId, columnNodeString);
text *columnText = cstring_to_text(columnName); text *columnText = cstring_to_text(columnName);
@ -167,17 +167,22 @@ BuildDistributionKeyFromColumnName(Relation distributedRelation, char *columnNam
/* /*
* ColumnNameToColumn returns the human-readable name of a column given a * ColumnToColumnName returns the human-readable name of a column given a
* relation identifier and the column's internal textual (Var) representation. * relation identifier and the column's internal textual (Var) representation.
* This function will raise an ERROR if no such column can be found or if the * This function will raise an ERROR if no such column can be found or if the
* provided Var refers to a system column. * provided Var refers to a system column.
*/ */
char * char *
ColumnNameToColumn(Oid relationId, char *columnNodeString) ColumnToColumnName(Oid relationId, char *columnNodeString)
{ {
Node *columnNode = stringToNode(columnNodeString); Node *columnNode = stringToNode(columnNodeString);
Assert(IsA(columnNode, Var)); if (columnNode == NULL || !IsA(columnNode, Var))
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("not a valid column")));
}
Var *column = (Var *) columnNode; Var *column = (Var *) columnNode;
AttrNumber columnNumber = column->varattno; AttrNumber columnNumber = column->varattno;

View File

@ -21,6 +21,6 @@
/* Remaining metadata utility functions */ /* Remaining metadata utility functions */
extern Var * BuildDistributionKeyFromColumnName(Relation distributedRelation, extern Var * BuildDistributionKeyFromColumnName(Relation distributedRelation,
char *columnName); char *columnName);
extern char * ColumnNameToColumn(Oid relationId, char *columnNodeString); extern char * ColumnToColumnName(Oid relationId, char *columnNodeString);
#endif /* DISTRIBUTION_COLUMN_H */ #endif /* DISTRIBUTION_COLUMN_H */

View File

@ -203,6 +203,24 @@ SELECT partmethod, column_to_column_name(logicalrelid, partkey) FROM pg_dist_par
h | id h | id
(1 row) (1 row)
-- test column_to_column_name with illegal arguments
SELECT column_to_column_name(1204127312,'');
ERROR: not a valid column
SELECT column_to_column_name('customers','');
ERROR: not a valid column
SELECT column_to_column_name('pg_dist_node'::regclass, NULL);
column_to_column_name
-----------------------
(1 row)
SELECT column_to_column_name('pg_dist_node'::regclass,'{FROMEXPR :fromlist ({RANGETBLREF :rtindex 1 }) :quals <>}');
ERROR: not a valid column
-- test column_name_to_column with illegal arguments
SELECT column_name_to_column(1204127312,'');
ERROR: could not open relation with OID 1204127312
SELECT column_name_to_column('customers','notacolumn');
ERROR: column "notacolumn" of relation "customers" does not exist
-- make one huge shard and manually inspect shard row -- make one huge shard and manually inspect shard row
SELECT create_monolithic_shard_row('customers') AS new_shard_id SELECT create_monolithic_shard_row('customers') AS new_shard_id
\gset \gset
@ -486,73 +504,73 @@ SELECT create_distributed_table('users_table_count', 'user_id');
SELECT relation_count_in_query($$-- we can support arbitrary subqueries within UNIONs SELECT relation_count_in_query($$-- we can support arbitrary subqueries within UNIONs
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
FROM FROM
( SELECT ( SELECT
*, random() *, random()
FROM FROM
(SELECT (SELECT
"t"."user_id", "t"."time", unnest("t"."collected_events") AS "event_types" "t"."user_id", "t"."time", unnest("t"."collected_events") AS "event_types"
FROM FROM
( SELECT ( SELECT
"t1"."user_id", min("t1"."time") AS "time", array_agg(("t1"."event") ORDER BY TIME ASC, event DESC) AS collected_events "t1"."user_id", min("t1"."time") AS "time", array_agg(("t1"."event") ORDER BY TIME ASC, event DESC) AS collected_events
FROM ( FROM (
(SELECT (SELECT
* *
FROM FROM
(SELECT (SELECT
events_table."time", 0 AS event, events_table."user_id" events_table."time", 0 AS event, events_table."user_id"
FROM FROM
"events_table_count" as events_table "events_table_count" as events_table
WHERE WHERE
events_table.event_type IN (1, 2) ) events_subquery_1) events_table.event_type IN (1, 2) ) events_subquery_1)
UNION UNION
(SELECT * (SELECT *
FROM FROM
( (
SELECT * FROM SELECT * FROM
( (
SELECT SELECT
max("events_table_count"."time"), max("events_table_count"."time"),
0 AS event, 0 AS event,
"events_table_count"."user_id" "events_table_count"."user_id"
FROM FROM
"events_table_count", users_table_count as "users" "events_table_count", users_table_count as "users"
WHERE WHERE
"events_table_count".user_id = users.user_id AND "events_table_count".user_id = users.user_id AND
"events_table_count".event_type IN (1, 2) "events_table_count".event_type IN (1, 2)
GROUP BY "events_table_count"."user_id" GROUP BY "events_table_count"."user_id"
) as events_subquery_5 ) as events_subquery_5
) events_subquery_2) ) events_subquery_2)
UNION UNION
(SELECT * (SELECT *
FROM FROM
(SELECT (SELECT
"events_table_count"."time", 2 AS event, "events_table_count"."user_id" "events_table_count"."time", 2 AS event, "events_table_count"."user_id"
FROM FROM
"events_table_count" "events_table_count"
WHERE WHERE
event_type IN (3, 4) ) events_subquery_3) event_type IN (3, 4) ) events_subquery_3)
UNION UNION
(SELECT * (SELECT *
FROM FROM
(SELECT (SELECT
"events_table_count"."time", 3 AS event, "events_table_count"."user_id" "events_table_count"."time", 3 AS event, "events_table_count"."user_id"
FROM FROM
"events_table_count" "events_table_count"
WHERE WHERE
event_type IN (5, 6)) events_subquery_4) event_type IN (5, 6)) events_subquery_4)
) t1 ) t1
GROUP BY "t1"."user_id") AS t) "q" GROUP BY "t1"."user_id") AS t) "q"
INNER JOIN INNER JOIN
(SELECT (SELECT
"events_table_count"."user_id" "events_table_count"."user_id"
FROM FROM
users_table_count as "events_table_count" users_table_count as "events_table_count"
WHERE WHERE
value_1 > 0 and value_1 < 4) AS t value_1 > 0 and value_1 < 4) AS t
ON (t.user_id = q.user_id)) as final_query ON (t.user_id = q.user_id)) as final_query
GROUP BY GROUP BY
types types
ORDER BY ORDER BY
types;$$); types;$$);
relation_count_in_query relation_count_in_query
------------------------- -------------------------

View File

@ -150,6 +150,16 @@ VALUES
SELECT partmethod, column_to_column_name(logicalrelid, partkey) FROM pg_dist_partition SELECT partmethod, column_to_column_name(logicalrelid, partkey) FROM pg_dist_partition
WHERE logicalrelid = 'customers'::regclass; WHERE logicalrelid = 'customers'::regclass;
-- test column_to_column_name with illegal arguments
SELECT column_to_column_name(1204127312,'');
SELECT column_to_column_name('customers','');
SELECT column_to_column_name('pg_dist_node'::regclass, NULL);
SELECT column_to_column_name('pg_dist_node'::regclass,'{FROMEXPR :fromlist ({RANGETBLREF :rtindex 1 }) :quals <>}');
-- test column_name_to_column with illegal arguments
SELECT column_name_to_column(1204127312,'');
SELECT column_name_to_column('customers','notacolumn');
-- make one huge shard and manually inspect shard row -- make one huge shard and manually inspect shard row
SELECT create_monolithic_shard_row('customers') AS new_shard_id SELECT create_monolithic_shard_row('customers') AS new_shard_id
\gset \gset