29
29
#include "parser/parse_func.h"
30
30
#include "parser/parse_relation.h"
31
31
#include "parser/parse_type.h"
32
+ #include "parser/parsetree.h"
32
33
#include "utils/builtins.h"
33
34
#include "utils/fmgroids.h"
34
35
#include "utils/lsyscache.h"
@@ -42,6 +43,7 @@ static Oid **argtype_inherit(int nargs, Oid *argtypes);
42
43
static int find_inheritors (Oid relid , Oid * * supervec );
43
44
static Oid * * gen_cross_product (InhPaths * arginh , int nargs );
44
45
static void unknown_attribute (ParseState * pstate , Node * relref , char * attname );
46
+ static bool check_pg_get_expr_arg (ParseState * pstate , Node * arg , int netlevelsup );
45
47
46
48
47
49
/*
@@ -1439,9 +1441,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
1439
1441
void
1440
1442
check_pg_get_expr_args (ParseState * pstate , Oid fnoid , List * args )
1441
1443
{
1442
- bool allowed = false;
1443
1444
Node * arg ;
1444
- int netlevelsup ;
1445
1445
1446
1446
/* if not being called for pg_get_expr, do nothing */
1447
1447
if (fnoid != F_PG_GET_EXPR && fnoid != F_PG_GET_EXPR_EXT )
@@ -1453,59 +1453,91 @@ check_pg_get_expr_args(ParseState *pstate, Oid fnoid, List *args)
1453
1453
1454
1454
/*
1455
1455
* The first argument must be a Var referencing one of the allowed
1456
- * system-catalog columns. It could be a join alias Var, though.
1456
+ * system-catalog columns. It could be a join alias Var or subquery
1457
+ * reference Var, though, so we need a recursive subroutine to chase
<
8000
td data-grid-cell-id="diff-4f5a8d08e1850109ddee47a33c6d76fb4fa5ab98408655e402da58e716fd8c2f-1456-1458-0" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionNum-bgColor, var(--diffBlob-addition-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">
1458
+ * through those possibilities.
1457
1459
*/
1458
1460
Assert (list_length (args ) > 1 );
1459
1461
arg = (Node * ) linitial (args );
1460
- netlevelsup = 0 ;
1461
1462
1462
- restart :
1463
- if (IsA (arg , Var ))
1463
+ if (!check_pg_get_expr_arg (pstate , arg , 0 ))
1464
+ ereport (ERROR ,
1465
+ (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
1466
+ errmsg ("argument to pg_get_expr() must come from system catalogs" )));
1467
+ }
1468
+
1469
+ static bool
1470
+ check_pg_get_expr_arg (ParseState * pstate , Node * arg , int netlevelsup )
1471
+ {
1472
+ if (arg && IsA (arg , Var ))
1464
1473
{
1465
1474
Var * var = (Var * ) arg ;
1466
1475
RangeTblEntry * rte ;
1476
+ AttrNumber attnum ;
1467
1477
1468
1478
netlevelsup += var -> varlevelsup ;
1469
1479
rte = GetRTEByRangeTablePosn (pstate , var -> varno , netlevelsup );
1480
+ attnum = var -> varattno ;
1470
1481
1471
1482
if (rte -> rtekind == RTE_JOIN )
1472
1483
{
1473
- /* Expand join alias reference */
1474
- if (var -> varattno > 0 &&
1475
- var -> varattno <= list_length (rte -> joinaliasvars ))
1484
+ /* Recursively examine join alias variable */
1485
+ if (attnum > 0 &&
1486
+ attnum <= list_length (rte -> joinaliasvars ))
1476
1487
{
1477
- arg = (Node * ) list_nth (rte -> joinaliasvars , var -> varattno - 1 );
1478
- goto restart ;
1488
+ arg = (Node * ) list_nth (rte -> joinaliasvars , attnum - 1 );
1489
+ return check_pg_get_expr_arg ( pstate , arg , netlevelsup ) ;
1479
1490
}
1480
1491
}
1492
+ else if (rte -> rtekind == RTE_SUBQUERY )
1493
+ {
1494
+ /* Subselect-in-FROM: examine sub-select's output expr */
1495
+ TargetEntry * ste = get_tle_by_resno (rte -> subquery -> targetList ,
1496
+ attnum );
1497
+ ParseState mypstate ;
1498
+
1499
+ if (ste == NULL || ste -> resdom -> resjunk )
1500
+ elog (ERROR , "subquery %s does not have attribute %d" ,
1501
+ rte -> eref -> aliasname , attnum );
1502
+ arg = (Node * ) ste -> expr ;
1503
+
1504
+ /*
628C
1505
+ * Recurse into the sub-select to see what its expr refers to.
1506
+ * We have to build an additional level of ParseState to keep in
1507
+ * step with varlevelsup in the subselect.
1508
+ */
1509
+ MemSet (& mypstate , 0 , sizeof (mypstate ));
1510
+ mypstate .parentParseState = pstate ;
1511
+ mypstate .p_rtable = rte -> subquery -> rtable ;
1512
+ /* don't bother filling the rest of the fake pstate */
1513
+
1514
+ return check_pg_get_expr_arg (& mypstate , arg , 0 );
1515
+ }
1481
1516
else if (rte -> rtekind == RTE_RELATION )
1482
1517
{
1483
1518
if (rte -> relid == get_system_catalog_relid (IndexRelationName ))
1484
1519
{
1485
- if (var -> varattno == Anum_pg_index_indexprs ||
1486
- var -> varattno == Anum_pg_index_indpred )
1487
- allowed = true;
1520
+ if (attnum == Anum_pg_index_indexprs ||
1521
+ attnum == Anum_pg_index_indpred )
1522
+ return true;
1488
1523
}
1489
1524
else if (rte -> relid == get_system_catalog_relid (AttrDefaultRelationName ))
1490
1525
{
1491
- if (var -> varattno == Anum_pg_attrdef_adbin )
1492
- allowed = true;
1526
+ if (attnum == Anum_pg_attrdef_adbin )
1527
+ return true;
1493
1528
}
1494
1529
else if (rte -> relid == get_system_catalog_relid (ConstraintRelationName ))
1495
1530
{
1496
- if (var -> varattno == Anum_pg_constraint_conbin )
1497
- allowed = true;
1531
+ if (attnum == Anum_pg_constraint_conbin )
1532
+ return true;
1498
1533
}
1499
1534
else if (rte -> relid == get_system_catalog_relid (TypeRelationName ))
1500
1535
{
1501
- if (var -> varattno == Anum_pg_type_typdefaultbin )
1502
- allowed = true;
1536
+ if (attnum == Anum_pg_type_typdefaultbin )
1537
+ return true;
1503
1538
}
1504
1539
}
1505
1540
}
1506
1541
1507
- if (!allowed )
1508
- ereport (ERROR ,
1509
- (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
1510
- errmsg ("argument to pg_get_expr() must come from system catalogs" )));
1542
+ return false;
1511
1543
}
0 commit comments