On 07/03/2015 10:03 AM, Noah Misch wrote:
> (7) Using an aggregate function in a policy predicate elicits an inapposite
> error message due to use of EXPR_KIND_WHERE for parse analysis. Need a new
> ParseExprKind. Test case:
Patch attached. Comments?
Joe
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 4642d7c..d8ef496 100644
*** a/src/backend/commands/policy.c
--- b/src/backend/commands/policy.c
*************** CreatePolicy(CreatePolicyStmt *stmt)
*** 532,545 ****
NULL, false, false);
addRTEtoQuery(with_check_pstate, rte, false, true, true);
! qual = transformWhereClause(qual_pstate,
copyObject(stmt->qual),
! EXPR_KIND_WHERE,
"POLICY");
! with_check_qual = transformWhereClause(with_check_pstate,
copyObject(stmt->with_check),
! EXPR_KIND_WHERE,
"POLICY");
/* Fix up collation information */
--- 532,545 ----
NULL, false, false);
addRTEtoQuery(with_check_pstate, rte, false, true, true);
! qual = transformPolicyClause(qual_pstate,
copyObject(stmt->qual),
! EXPR_KIND_POLICY,
"POLICY");
! with_check_qual = transformPolicyClause(with_check_pstate,
copyObject(stmt->with_check),
! EXPR_KIND_POLICY,
"POLICY");
/* Fix up collation information */
*************** AlterPolicy(AlterPolicyStmt *stmt)
*** 704,711 ****
addRTEtoQuery(qual_pstate, rte, false, true, true);
! qual = transformWhereClause(qual_pstate, copyObject(stmt->qual),
! EXPR_KIND_WHERE,
"POLICY");
/* Fix up collation information */
--- 704,711 ----
addRTEtoQuery(qual_pstate, rte, false, true, true);
! qual = transformPolicyClause(qual_pstate, copyObject(stmt->qual),
! EXPR_KIND_POLICY,
"POLICY");
/* Fix up collation information */
*************** AlterPolicy(AlterPolicyStmt *stmt)
*** 726,734 ****
addRTEtoQuery(with_check_pstate, rte, false, true, true);
! with_check_qual = transformWhereClause(with_check_pstate,
copyObject(stmt->with_check),
! EXPR_KIND_WHERE,
"POLICY");
/* Fix up collation information */
--- 726,734 ----
addRTEtoQuery(with_check_pstate, rte, false, true, true);
! with_check_qual = transformPolicyClause(with_check_pstate,
copyObject(stmt->with_check),
! EXPR_KIND_POLICY,
"POLICY");
/* Fix up collation information */
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 478d8ca..b79e73d 100644
*** a/src/backend/parser/parse_agg.c
--- b/src/backend/parser/parse_agg.c
*************** check_agglevels_and_constraints(ParseSta
*** 373,378 ****
--- 373,381 ----
case EXPR_KIND_WHERE:
errkind = true;
break;
+ case EXPR_KIND_POLICY:
+ errkind = true;
+ break;
case EXPR_KIND_HAVING:
/* okay */
break;
*************** transformWindowFuncCall(ParseState *psta
*** 770,775 ****
--- 773,781 ----
case EXPR_KIND_WHERE:
errkind = true;
break;
+ case EXPR_KIND_POLICY:
+ errkind = true;
+ break;
case EXPR_KIND_HAVING:
errkind = true;
break;
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 5980856..7063e5f 100644
*** a/src/backend/parser/parse_clause.c
--- b/src/backend/parser/parse_clause.c
*************** transformWhereClause(ParseState *pstate,
*** 1465,1470 ****
--- 1465,1491 ----
return qual;
}
+ /*
+ * transformPolicyClause -
+ * Transform USING and WITH CHECK expr to make sure it is of type boolean.
+ *
+ * constructName does not affect the semantics, but is used in error messages
+ */
+ Node *
+ transformPolicyClause(ParseState *pstate, Node *clause,
+ ParseExprKind exprKind, const char *constructName)
+ {
+ Node *qual;
+
+ if (clause == NULL)
+ return NULL;
+
+ qual = transformExpr(pstate, clause, exprKind);
+
+ qual = coerce_to_boolean(pstate, qual, constructName);
+
+ return qual;
+ }
/*
* transformLimitClause -
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 0ff46dd..fa77ef1 100644
*** a/src/backend/parser/parse_expr.c
--- b/src/backend/parser/parse_expr.c
*************** transformSubLink(ParseState *pstate, Sub
*** 1672,1677 ****
--- 1672,1678 ----
case EXPR_KIND_FROM_SUBSELECT:
case EXPR_KIND_FROM_FUNCTION:
case EXPR_KIND_WHERE:
+ case EXPR_KIND_POLICY:
case EXPR_KIND_HAVING:
case EXPR_KIND_FILTER:
case EXPR_KIND_WINDOW_PARTITION:
*************** ParseExprKindName(ParseExprKind exprKind
*** 3173,3178 ****
--- 3174,3181 ----
return "function in FROM";
case EXPR_KIND_WHERE:
return "WHERE";
+ case EXPR_KIND_POLICY:
+ return "POLICY";
case EXPR_KIND_HAVING:
return "HAVING";
case EXPR_KIND_FILTER:
diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h
index 77619e3..63e83e1 100644
*** a/src/include/parser/parse_clause.h
--- b/src/include/parser/parse_clause.h
*************** extern bool interpretOidsOption(List *de
*** 24,29 ****
--- 24,31 ----
extern Node *transformWhereClause(ParseState *pstate, Node *clause,
ParseExprKind exprKind, const char *constructName);
+ extern Node *transformPolicyClause(ParseState *pstate, Node *clause,
+ ParseExprKind exprKind, const char *constructName);
extern Node *transformLimitClause(ParseState *pstate, Node *clause,
ParseExprKind exprKind, const char *constructName);
extern List *transformGroupClause(ParseState *pstate, List *grouplist,
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index 7ecaffc..5249945 100644
*** a/src/include/parser/parse_node.h
--- b/src/include/parser/parse_node.h
*************** typedef enum ParseExprKind
*** 63,69 ****
EXPR_KIND_INDEX_PREDICATE, /* index predicate */
EXPR_KIND_ALTER_COL_TRANSFORM, /* transform expr in ALTER COLUMN TYPE */
EXPR_KIND_EXECUTE_PARAMETER, /* parameter value in EXECUTE */
! EXPR_KIND_TRIGGER_WHEN /* WHEN condition in CREATE TRIGGER */
} ParseExprKind;
--- 63,70 ----
EXPR_KIND_INDEX_PREDICATE, /* index predicate */
EXPR_KIND_ALTER_COL_TRANSFORM, /* transform expr in ALTER COLUMN TYPE */
EXPR_KIND_EXECUTE_PARAMETER, /* parameter value in EXECUTE */
! EXPR_KIND_TRIGGER_WHEN, /* WHEN condition in CREATE TRIGGER */
! EXPR_KIND_POLICY /* USING or WITH CHECK expr in policy */
} ParseExprKind;
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
index b146da3..23e9a55 100644
*** a/src/test/regress/expected/rowsecurity.out
--- b/src/test/regress/expected/rowsecurity.out
*************** CREATE RULE "_RETURN" AS ON SELECT TO t
*** 3024,3029 ****
--- 3024,3038 ----
SELECT * FROM generate_series(1,5) t0(c); -- succeeds
ROLLBACK;
--
+ -- Policy expression handling
+ --
+ BEGIN;
+ SET row_security = FORCE;
+ CREATE TABLE t (c) AS VALUES ('bar'::text);
+ CREATE POLICY p ON t USING (max(c)); -- fails: aggregate functions are not allowed in POLICY
+ ERROR: aggregate functions are not allowed in POLICY
+ ROLLBACK;
+ --
-- Clean up objects
--
RESET SESSION AUTHORIZATION;
diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
index 54f2c89..47a2703 100644
*** a/src/test/regress/sql/rowsecurity.sql
--- b/src/test/regress/sql/rowsecurity.sql
*************** CREATE RULE "_RETURN" AS ON SELECT TO t
*** 1290,1295 ****
--- 1290,1304 ----
ROLLBACK;
--
+ -- Policy expression handling
+ --
+ BEGIN;
+ SET row_security = FORCE;
+ CREATE TABLE t (c) AS VALUES ('bar'::text);
+ CREATE POLICY p ON t USING (max(c)); -- fails: aggregate functions are not allowed in POLICY
+ ROLLBACK;
+
+ --
-- Clean up objects
--
RESET SESSION AUTHORIZATION;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers