PostgreSQL Source Code git master
Loading...
Searching...
No Matches
parse_relation.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "access/relation.h"
#include "access/table.h"
#include "catalog/heap.h"
#include "catalog/namespace.h"
#include "funcapi.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_enr.h"
#include "parser/parse_relation.h"
#include "parser/parse_type.h"
#include "parser/parsetree.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
Include dependency graph for parse_relation.c:

Go to the source code of this file.

Data Structures

struct  FuzzyAttrMatchState
 

Macros

#define MAX_FUZZY_DISTANCE   3
 

Functions

static ParseNamespaceItemscanNameSpaceForRefname (ParseState *pstate, const char *refname, int location)
 
static ParseNamespaceItemscanNameSpaceForRelid (ParseState *pstate, Oid relid, int location)
 
static void check_lateral_ref_ok (ParseState *pstate, ParseNamespaceItem *nsitem, int location)
 
static int scanRTEForColumn (ParseState *pstate, RangeTblEntry *rte, Alias *eref, const char *colname, int location, int fuzzy_rte_penalty, FuzzyAttrMatchState *fuzzystate)
 
static void markRTEForSelectPriv (ParseState *pstate, int rtindex, AttrNumber col)
 
static void expandRelation (Oid relid, Alias *eref, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
 
static void expandTupleDesc (TupleDesc tupdesc, Alias *eref, int count, int offset, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
 
static int specialAttNum (const char *attname)
 
static bool rte_visible_if_lateral (ParseState *pstate, RangeTblEntry *rte)
 
static bool rte_visible_if_qualified (ParseState *pstate, RangeTblEntry *rte)
 
ParseNamespaceItemrefnameNamespaceItem (ParseState *pstate, const char *schemaname, const char *refname, int location, int *sublevels_up)
 
CommonTableExprscanNameSpaceForCTE (ParseState *pstate, const char *refname, Index *ctelevelsup)
 
static bool isFutureCTE (ParseState *pstate, const char *refname)
 
bool scanNameSpaceForENR (ParseState *pstate, const char *refname)
 
static RangeTblEntrysearchRangeTableForRel (ParseState *pstate, RangeVar *relation)
 
void checkNameSpaceConflicts (ParseState *pstate, List *namespace1, List *namespace2)
 
ParseNamespaceItemGetNSItemByRangeTablePosn (ParseState *pstate, int varno, int sublevels_up)
 
ParseNamespaceItemGetNSItemByVar (ParseState *pstate, Var *var)
 
RangeTblEntryGetRTEByRangeTablePosn (ParseState *pstate, int varno, int sublevels_up)
 
CommonTableExprGetCTEForRTE (ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
 
static void updateFuzzyAttrMatchState (int fuzzy_rte_penalty, FuzzyAttrMatchState *fuzzystate, RangeTblEntry *rte, const char *actual, const char *match, int attnum)
 
NodescanNSItemForColumn (ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, const char *colname, int location)
 
NodecolNameToVar (ParseState *pstate, const char *colname, bool localonly, int location)
 
static FuzzyAttrMatchStatesearchRangeTableForCol (ParseState *pstate, const char *alias, const char *colname, int location)
 
void markNullableIfNeeded (ParseState *pstate, Var *var)
 
void markVarForSelectPriv (ParseState *pstate, Var *var)
 
static void buildRelationAliases (TupleDesc tupdesc, Alias *alias, Alias *eref)
 
static charchooseScalarFunctionAlias (Node *funcexpr, char *funcname, Alias *alias, int nfuncs)
 
static ParseNamespaceItembuildNSItemFromTupleDesc (RangeTblEntry *rte, Index rtindex, RTEPermissionInfo *perminfo, TupleDesc tupdesc)
 
static ParseNamespaceItembuildNSItemFromLists (RangeTblEntry *rte, Index rtindex, List *coltypes, List *coltypmods, List *colcollations)
 
Relation parserOpenTable (ParseState *pstate, const RangeVar *relation, LOCKMODE lockmode)
 
ParseNamespaceItemaddRangeTableEntry (ParseState *pstate, RangeVar *relation, Alias *alias, bool inh, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForRelation (ParseState *pstate, Relation rel, LOCKMODE lockmode, Alias *alias, bool inh, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForSubquery (ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForFunction (ParseState *pstate, List *funcnames, List *funcexprs, List *coldeflists, RangeFunction *rangefunc, bool lateral, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForTableFunc (ParseState *pstate, TableFunc *tf, Alias *alias, bool lateral, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForGraphTable (ParseState *pstate, Oid graphid, GraphPattern *graph_pattern, List *columns, List *colnames, Alias *alias, bool lateral, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForValues (ParseState *pstate, List *exprs, List *coltypes, List *coltypmods, List *colcollations, Alias *alias, bool lateral, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForJoin (ParseState *pstate, List *colnames, ParseNamespaceColumn *nscolumns, JoinType jointype, int nummergedcols, List *aliasvars, List *leftcols, List *rightcols, Alias *join_using_alias, Alias *alias, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForCTE (ParseState *pstate, CommonTableExpr *cte, Index levelsup, RangeVar *rv, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForENR (ParseState *pstate, RangeVar *rv, bool inFromCl)
 
ParseNamespaceItemaddRangeTableEntryForGroup (ParseState *pstate, List *groupClauses)
 
bool isLockedRefname (ParseState *pstate, const char *refname)
 
void addNSItemToQuery (ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
 
void expandRTE (RangeTblEntry *rte, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
 
ListexpandNSItemVars (ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, int location, List **colnames)
 
ListexpandNSItemAttrs (ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, bool require_col_privs, int location)
 
charget_rte_attribute_name (RangeTblEntry *rte, AttrNumber attnum)
 
bool get_rte_attribute_is_dropped (RangeTblEntry *rte, AttrNumber attnum)
 
TargetEntryget_tle_by_resno (List *tlist, AttrNumber resno)
 
RowMarkClauseget_parse_rowmark (Query *qry, Index rtindex)
 
int attnameAttNum (Relation rd, const char *attname, bool sysColOK)
 
const NameDataattnumAttName (Relation rd, int attid)
 
Oid attnumTypeId (Relation rd, int attid)
 
Oid attnumCollationId (Relation rd, int attid)
 
void errorMissingRTE (ParseState *pstate, RangeVar *relation)
 
void errorMissingColumn (ParseState *pstate, const char *relname, const char *colname, int location)
 
static ParseNamespaceItemfindNSItemForRTE (ParseState *pstate, RangeTblEntry *rte)
 
RTEPermissionInfoaddRTEPermissionInfo (List **rteperminfos, RangeTblEntry *rte)
 
RTEPermissionInfogetRTEPermissionInfo (List *rteperminfos, RangeTblEntry *rte)
 

Macro Definition Documentation

◆ MAX_FUZZY_DISTANCE

#define MAX_FUZZY_DISTANCE   3

Definition at line 72 of file parse_relation.c.

Function Documentation

◆ addNSItemToQuery()

void addNSItemToQuery ( ParseState pstate,
ParseNamespaceItem nsitem,
bool  addToJoinList,
bool  addToRelNameSpace,
bool  addToVarNameSpace 
)

Definition at line 2825 of file parse_relation.c.

2828{
2829 if (addToJoinList)
2830 {
2832
2833 rtr->rtindex = nsitem->p_rtindex;
2834 pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
2835 }
2837 {
2838 /* Set the new nsitem's visibility flags correctly */
2839 nsitem->p_rel_visible = addToRelNameSpace;
2840 nsitem->p_cols_visible = addToVarNameSpace;
2841 nsitem->p_lateral_only = false;
2842 nsitem->p_lateral_ok = true;
2843 pstate->p_namespace = lappend(pstate->p_namespace, nsitem);
2844 }
2845}
List * lappend(List *list, void *datum)
Definition list.c:339
#define makeNode(_type_)
Definition nodes.h:159
static int fb(int x)
List * p_namespace
Definition parse_node.h:222
List * p_joinlist
Definition parse_node.h:220

References fb(), lappend(), makeNode, ParseState::p_joinlist, and ParseState::p_namespace.

Referenced by addNSItemForReturning(), AddRelationNewConstraints(), AlterPolicy(), CreatePolicy(), CreateTriggerFiringOn(), DefineRelation(), DoCopy(), insert_property_records(), setTargetTable(), test_rls_hooks_permissive(), test_rls_hooks_restrictive(), transformAlterTableStmt(), transformIndexStmt(), transformInsertStmt(), transformMergeStmt(), transformOnConflictClause(), transformPartitionSpec(), TransformPubWhereClauses(), transformRuleStmt(), transformSetOperationStmt(), transformStatsStmt(), and transformValuesClause().

◆ addRangeTableEntry()

ParseNamespaceItem * addRangeTableEntry ( ParseState pstate,
RangeVar relation,
Alias alias,
bool  inh,
bool  inFromCl 
)

Definition at line 1511 of file parse_relation.c.

1516{
1519 char *refname = alias ? alias->aliasname : relation->relname;
1520 LOCKMODE lockmode;
1521 Relation rel;
1523
1524 Assert(pstate != NULL);
1525
1526 rte->rtekind = RTE_RELATION;
1527 rte->alias = alias;
1528
1529 /*
1530 * Identify the type of lock we'll need on this relation. It's not the
1531 * query's target table (that case is handled elsewhere), so we need
1532 * either RowShareLock if it's locked by FOR UPDATE/SHARE, or plain
1533 * AccessShareLock otherwise.
1534 */
1535 lockmode = isLockedRefname(pstate, refname) ? RowShareLock : AccessShareLock;
1536
1537 /*
1538 * Get the rel's OID. This access also ensures that we have an up-to-date
1539 * relcache entry for the rel. Since this is typically the first access
1540 * to a rel in a statement, we must open the rel with the proper lockmode.
1541 */
1542 rel = parserOpenTable(pstate, relation, lockmode);
1543 rte->relid = RelationGetRelid(rel);
1544 rte->inh = inh;
1545 rte->relkind = rel->rd_rel->relkind;
1546 rte->rellockmode = lockmode;
1547
1548 /*
1549 * Build the list of effective column names using user-supplied aliases
1550 * and/or actual column names.
1551 */
1552 rte->eref = makeAlias(refname, NIL);
1553 buildRelationAliases(rel->rd_att, alias, rte->eref);
1554
1555 /*
1556 * Set flags and initialize access permissions.
1557 *
1558 * The initial default on access checks is always check-for-READ-access,
1559 * which is the right thing for all except target tables.
1560 */
1561 rte->lateral = false;
1562 rte->inFromCl = inFromCl;
1563
1565 perminfo->requiredPerms = ACL_SELECT;
1566
1567 /*
1568 * Add completed RTE to pstate's range table list, so that we know its
1569 * index. But we don't add it to the join list --- caller must do that if
1570 * appropriate.
1571 */
1572 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1573
1574 /*
1575 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
1576 * list --- caller must do that if appropriate.
1577 */
1579 perminfo, rel->rd_att);
1580
1581 /*
1582 * Drop the rel refcount, but keep the access lock till end of transaction
1583 * so that the table can't be deleted or have its schema modified
1584 * underneath us.
1585 */
1586 table_close(rel, NoLock);
1587
1588 return nsitem;
1589}
#define Assert(condition)
Definition c.h:999
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
#define AccessShareLock
Definition lockdefs.h:36
#define RowShareLock
Definition lockdefs.h:37
Alias * makeAlias(const char *aliasname, List *colnames)
Definition makefuncs.c:438
Relation parserOpenTable(ParseState *pstate, const RangeVar *relation, LOCKMODE lockmode)
static ParseNamespaceItem * buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, RTEPermissionInfo *perminfo, TupleDesc tupdesc)
bool isLockedRefname(ParseState *pstate, const char *refname)
RTEPermissionInfo * addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte)
static void buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
@ RTE_RELATION
#define ACL_SELECT
Definition parsenodes.h:77
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define RelationGetRelid(relation)
Definition rel.h:516
char * aliasname
Definition primnodes.h:52
List * p_rteperminfos
Definition parse_node.h:216
List * p_rtable
Definition parse_node.h:215
char * relname
Definition primnodes.h:84
TupleDesc rd_att
Definition rel.h:112
Form_pg_class rd_rel
Definition rel.h:111
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126

References AccessShareLock, ACL_SELECT, addRTEPermissionInfo(), Alias::aliasname, Assert, buildNSItemFromTupleDesc(), buildRelationAliases(), fb(), isLockedRefname(), lappend(), list_length(), makeAlias(), makeNode, NIL, NoLock, ParseState::p_rtable, ParseState::p_rteperminfos, parserOpenTable(), RelationData::rd_att, RelationData::rd_rel, RelationGetRelid, RangeVar::relname, RowShareLock, RTE_RELATION, and table_close().

Referenced by transformTableEntry().

◆ addRangeTableEntryForCTE()

ParseNamespaceItem * addRangeTableEntryForCTE ( ParseState pstate,
CommonTableExpr cte,
Index  levelsup,
RangeVar rv,
bool  inFromCl 
)

Definition at line 2447 of file parse_relation.c.

2452{
2454 Alias *alias = rv->alias;
2455 char *refname = alias ? alias->aliasname : cte->ctename;
2456 Alias *eref;
2457 int numaliases;
2458 int varattno;
2459 ListCell *lc;
2460 int n_dontexpand_columns = 0;
2462
2463 Assert(pstate != NULL);
2464
2465 rte->rtekind = RTE_CTE;
2466 rte->ctename = cte->ctename;
2467 rte->ctelevelsup = levelsup;
2468
2469 /* Self-reference if and only if CTE's parse analysis isn't completed */
2470 rte->self_reference = !IsA(cte->ctequery, Query);
2471 Assert(cte->cterecursive || !rte->self_reference);
2472 /* Bump the CTE's refcount if this isn't a self-reference */
2473 if (!rte->self_reference)
2474 cte->cterefcount++;
2475
2476 /*
2477 * We throw error if the CTE is INSERT/UPDATE/DELETE/MERGE without
2478 * RETURNING. This won't get checked in case of a self-reference, but
2479 * that's OK because data-modifying CTEs aren't allowed to be recursive
2480 * anyhow.
2481 */
2482 if (IsA(cte->ctequery, Query))
2483 {
2484 Query *ctequery = (Query *) cte->ctequery;
2485
2486 if (ctequery->commandType != CMD_SELECT &&
2487 ctequery->returningList == NIL)
2488 ereport(ERROR,
2490 errmsg("WITH query \"%s\" does not have a RETURNING clause",
2491 cte->ctename),
2492 parser_errposition(pstate, rv->location)));
2493 }
2494
2495 rte->coltypes = list_copy(cte->ctecoltypes);
2496 rte->coltypmods = list_copy(cte->ctecoltypmods);
2497 rte->colcollations = list_copy(cte->ctecolcollations);
2498
2499 rte->alias = alias;
2500 if (alias)
2501 eref = copyObject(alias);
2502 else
2503 eref = makeAlias(refname, NIL);
2504 numaliases = list_length(eref->colnames);
2505
2506 /* fill in any unspecified alias columns */
2507 varattno = 0;
2508 foreach(lc, cte->ctecolnames)
2509 {
2510 varattno++;
2511 if (varattno > numaliases)
2512 eref->colnames = lappend(eref->colnames, lfirst(lc));
2513 }
2514 if (varattno < numaliases)
2515 ereport(ERROR,
2517 errmsg("table \"%s\" has %d columns available but %d columns specified",
2518 refname, varattno, numaliases)));
2519
2520 rte->eref = eref;
2521
2522 if (cte->search_clause)
2523 {
2524 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->search_clause->search_seq_column));
2525 if (cte->search_clause->search_breadth_first)
2526 rte->coltypes = lappend_oid(rte->coltypes, RECORDOID);
2527 else
2528 rte->coltypes = lappend_oid(rte->coltypes, RECORDARRAYOID);
2529 rte->coltypmods = lappend_int(rte->coltypmods, -1);
2530 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2531
2533 }
2534
2535 if (cte->cycle_clause)
2536 {
2537 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->cycle_clause->cycle_mark_column));
2538 rte->coltypes = lappend_oid(rte->coltypes, cte->cycle_clause->cycle_mark_type);
2539 rte->coltypmods = lappend_int(rte->coltypmods, cte->cycle_clause->cycle_mark_typmod);
2540 rte->colcollations = lappend_oid(rte->colcollations, cte->cycle_clause->cycle_mark_collation);
2541
2542 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->cycle_clause->cycle_path_column));
2543 rte->coltypes = lappend_oid(rte->coltypes, RECORDARRAYOID);
2544 rte->coltypmods = lappend_int(rte->coltypmods, -1);
2545 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2546
2548 }
2549
2550 /*
2551 * Set flags and access permissions.
2552 *
2553 * Subqueries are never checked for access rights, so no need to perform
2554 * addRTEPermissionInfo().
2555 */
2556 rte->lateral = false;
2557 rte->inFromCl = inFromCl;
2558
2559 /*
2560 * Add completed RTE to pstate's range table list, so that we know its
2561 * index. But we don't add it to the join list --- caller must do that if
2562 * appropriate.
2563 */
2564 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2565
2566 /*
2567 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2568 * list --- caller must do that if appropriate.
2569 */
2571 rte->coltypes, rte->coltypmods,
2572 rte->colcollations);
2573
2574 /*
2575 * The columns added by search and cycle clauses are not included in star
2576 * expansion in queries contained in the CTE.
2577 */
2578 if (rte->ctelevelsup > 0)
2579 for (int i = 0; i < n_dontexpand_columns; i++)
2580 psi->p_nscolumns[list_length(psi->p_names->colnames) - 1 - i].p_dontexpand = true;
2581
2582 return psi;
2583}
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
int i
Definition isn.c:77
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_int(List *list, int datum)
Definition list.c:357
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
#define IsA(nodeptr, _type_)
Definition nodes.h:162
#define copyObject(obj)
Definition nodes.h:230
@ CMD_SELECT
Definition nodes.h:273
static char * errmsg
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
static ParseNamespaceItem * buildNSItemFromLists(RangeTblEntry *rte, Index rtindex, List *coltypes, List *coltypmods, List *colcollations)
@ RTE_CTE
#define lfirst(lc)
Definition pg_list.h:172
#define InvalidOid
Alias * alias
Definition primnodes.h:93
ParseLoc location
Definition primnodes.h:96
String * makeString(char *str)
Definition value.c:63

References RangeVar::alias, Alias::aliasname, Assert, buildNSItemFromLists(), CMD_SELECT, Query::commandType, copyObject, CommonTableExpr::ctename, CommonTableExpr::ctequery, ereport, errcode(), errmsg, ERROR, fb(), i, InvalidOid, IsA, lappend(), lappend_int(), lappend_oid(), lfirst, list_copy(), list_length(), RangeVar::location, makeAlias(), makeNode, makeString(), NIL, ParseState::p_rtable, parser_errposition(), Query::returningList, and RTE_CTE.

Referenced by getNSItemForSpecialRelationTypes().

◆ addRangeTableEntryForENR()

ParseNamespaceItem * addRangeTableEntryForENR ( ParseState pstate,
RangeVar rv,
bool  inFromCl 
)

Definition at line 2599 of file parse_relation.c.

2602{
2604 Alias *alias = rv->alias;
2605 char *refname = alias ? alias->aliasname : rv->relname;
2607 TupleDesc tupdesc;
2608 int attno;
2609
2610 Assert(pstate != NULL);
2611 enrmd = get_visible_ENR(pstate, rv->relname);
2612 Assert(enrmd != NULL);
2613
2614 switch (enrmd->enrtype)
2615 {
2617 rte->rtekind = RTE_NAMEDTUPLESTORE;
2618 break;
2619
2620 default:
2621 elog(ERROR, "unexpected enrtype: %d", enrmd->enrtype);
2622 return NULL; /* for fussy compilers */
2623 }
2624
2625 /*
2626 * Record dependency on a relation. This allows plans to be invalidated
2627 * if they access transition tables linked to a table that is altered.
2628 */
2629 rte->relid = enrmd->reliddesc;
2630
2631 /*
2632 * Build the list of effective column names using user-supplied aliases
2633 * and/or actual column names.
2634 */
2635 tupdesc = ENRMetadataGetTupDesc(enrmd);
2636 rte->eref = makeAlias(refname, NIL);
2637 buildRelationAliases(tupdesc, alias, rte->eref);
2638
2639 /* Record additional data for ENR, including column type info */
2640 rte->enrname = enrmd->name;
2641 rte->enrtuples = enrmd->enrtuples;
2642 rte->coltypes = NIL;
2643 rte->coltypmods = NIL;
2644 rte->colcollations = NIL;
2645 for (attno = 1; attno <= tupdesc->natts; ++attno)
2646 {
2647 Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
2648
2649 if (att->attisdropped)
2650 {
2651 /* Record zeroes for a dropped column */
2652 rte->coltypes = lappend_oid(rte->coltypes, InvalidOid);
2653 rte->coltypmods = lappend_int(rte->coltypmods, 0);
2654 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2655 }
2656 else
2657 {
2658 /* Let's just make sure we can tell this isn't dropped */
2659 if (att->atttypid == InvalidOid)
2660 elog(ERROR, "atttypid is invalid for non-dropped column in \"%s\"",
2661 rv->relname);
2662 rte->coltypes = lappend_oid(rte->coltypes, att->atttypid);
2663 rte->coltypmods = lappend_int(rte->coltypmods, att->atttypmod);
2664 rte->colcollations = lappend_oid(rte->colcollations,
2665 att->attcollation);
2666 }
2667 }
2668
2669 /*
2670 * Set flags and access permissions.
2671 *
2672 * ENRs are never checked for access rights, so no need to perform
2673 * addRTEPermissionInfo().
2674 */
2675 rte->lateral = false;
2676 rte->inFromCl = inFromCl;
2677
2678 /*
2679 * Add completed RTE to pstate's range table list, so that we know its
2680 * index. But we don't add it to the join list --- caller must do that if
2681 * appropriate.
2682 */
2683 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2684
2685 /*
2686 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2687 * list --- caller must do that if appropriate.
2688 */
2690 tupdesc);
2691}
#define elog(elevel,...)
Definition elog.h:228
EphemeralNamedRelationMetadata get_visible_ENR(ParseState *pstate, const char *refname)
Definition parse_enr.c:26
@ RTE_NAMEDTUPLESTORE
FormData_pg_attribute * Form_pg_attribute
TupleDesc ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd)
@ ENR_NAMED_TUPLESTORE
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

References RangeVar::alias, Alias::aliasname, Assert, buildNSItemFromTupleDesc(), buildRelationAliases(), elog, ENR_NAMED_TUPLESTORE, ENRMetadataGetTupDesc(), ERROR, fb(), get_visible_ENR(), InvalidOid, lappend(), lappend_int(), lappend_oid(), list_length(), makeAlias(), makeNode, TupleDescData::natts, NIL, ParseState::p_rtable, RangeVar::relname, RTE_NAMEDTUPLESTORE, and TupleDescAttr().

Referenced by getNSItemForSpecialRelationTypes().

◆ addRangeTableEntryForFunction()

ParseNamespaceItem * addRangeTableEntryForFunction ( ParseState pstate,
List funcnames,
List funcexprs,
List coldeflists,
RangeFunction rangefunc,
bool  lateral,
bool  inFromCl 
)

Definition at line 1771 of file parse_relation.c.

1778{
1780 Alias *alias = rangefunc->alias;
1781 Alias *eref;
1782 char *aliasname;
1783 int nfuncs = list_length(funcexprs);
1785 TupleDesc tupdesc;
1786 ListCell *lc1,
1787 *lc2,
1788 *lc3;
1789 int i;
1790 int j;
1791 int funcno;
1792 int natts,
1793 totalatts;
1794
1795 Assert(pstate != NULL);
1796
1797 rte->rtekind = RTE_FUNCTION;
1798 rte->relid = InvalidOid;
1799 rte->subquery = NULL;
1800 rte->functions = NIL; /* we'll fill this list below */
1801 rte->funcordinality = rangefunc->ordinality;
1802 rte->alias = alias;
1803
1804 /*
1805 * Choose the RTE alias name. We default to using the first function's
1806 * name even when there's more than one; which is maybe arguable but beats
1807 * using something constant like "table".
1808 */
1809 if (alias)
1810 aliasname = alias->aliasname;
1811 else
1812 aliasname = linitial(funcnames);
1813
1814 eref = makeAlias(aliasname, NIL);
1815 rte->eref = eref;
1816
1817 /* Process each function ... */
1819
1820 totalatts = 0;
1821 funcno = 0;
1823 {
1824 Node *funcexpr = (Node *) lfirst(lc1);
1825 char *funcname = (char *) lfirst(lc2);
1826 List *coldeflist = (List *) lfirst(lc3);
1830
1831 /* Initialize RangeTblFunction node */
1832 rtfunc->funcexpr = funcexpr;
1833 rtfunc->funccolnames = NIL;
1834 rtfunc->funccoltypes = NIL;
1835 rtfunc->funccoltypmods = NIL;
1836 rtfunc->funccolcollations = NIL;
1837 rtfunc->funcparams = NULL; /* not set until planning */
1838
1839 /*
1840 * Now determine if the function returns a simple or composite type.
1841 */
1843 &funcrettype,
1844 &tupdesc);
1845
1846 /*
1847 * A coldeflist is required if the function returns RECORD and hasn't
1848 * got a predetermined record type, and is prohibited otherwise. This
1849 * can be a bit confusing, so we expend some effort on delivering a
1850 * relevant error message.
1851 */
1852 if (coldeflist != NIL)
1853 {
1854 switch (functypclass)
1855 {
1856 case TYPEFUNC_RECORD:
1857 /* ok */
1858 break;
1859 case TYPEFUNC_COMPOSITE:
1861
1862 /*
1863 * If the function's raw result type is RECORD, we must
1864 * have resolved it using its OUT parameters. Otherwise,
1865 * it must have a named composite type.
1866 */
1867 if (exprType(funcexpr) == RECORDOID)
1868 ereport(ERROR,
1870 errmsg("a column definition list is redundant for a function with OUT parameters"),
1871 parser_errposition(pstate,
1872 exprLocation((Node *) coldeflist))));
1873 else
1874 ereport(ERROR,
1876 errmsg("a column definition list is redundant for a function returning a named composite type"),
1877 parser_errposition(pstate,
1878 exprLocation((Node *) coldeflist))));
1879 break;
1880 default:
1881 ereport(ERROR,
1883 errmsg("a column definition list is only allowed for functions returning \"record\""),
1884 parser_errposition(pstate,
1885 exprLocation((Node *) coldeflist))));
1886 break;
1887 }
1888 }
1889 else
1890 {
1892 ereport(ERROR,
1894 errmsg("a column definition list is required for functions returning \"record\""),
1895 parser_errposition(pstate, exprLocation(funcexpr))));
1896 }
1897
1900 {
1901 /* Composite data type, e.g. a table's row type */
1902 Assert(tupdesc);
1903 }
1904 else if (functypclass == TYPEFUNC_SCALAR)
1905 {
1906 /* Base data type, i.e. scalar */
1907 tupdesc = CreateTemplateTupleDesc(1);
1908 TupleDescInitEntry(tupdesc,
1909 (AttrNumber) 1,
1911 alias, nfuncs),
1913 exprTypmod(funcexpr),
1914 0);
1916 (AttrNumber) 1,
1917 exprCollation(funcexpr));
1918 TupleDescFinalize(tupdesc);
1919 }
1920 else if (functypclass == TYPEFUNC_RECORD)
1921 {
1922 ListCell *col;
1923
1924 /*
1925 * Use the column definition list to construct a tupdesc and fill
1926 * in the RangeTblFunction's lists. Limit number of columns to
1927 * MaxHeapAttributeNumber, because CheckAttributeNamesTypes will.
1928 */
1929 if (list_length(coldeflist) > MaxHeapAttributeNumber)
1930 ereport(ERROR,
1932 errmsg("column definition lists can have at most %d entries",
1934 parser_errposition(pstate,
1935 exprLocation((Node *) coldeflist))));
1936 tupdesc = CreateTemplateTupleDesc(list_length(coldeflist));
1937 i = 1;
1938 foreach(col, coldeflist)
1939 {
1940 ColumnDef *n = (ColumnDef *) lfirst(col);
1941 char *attrname;
1942 Oid attrtype;
1943 int32 attrtypmod;
1945
1946 attrname = n->colname;
1947 if (n->typeName->setof)
1948 ereport(ERROR,
1950 errmsg("column \"%s\" cannot be declared SETOF",
1951 attrname),
1952 parser_errposition(pstate, n->location)));
1953 typenameTypeIdAndMod(pstate, n->typeName,
1954 &attrtype, &attrtypmod);
1955 attrcollation = GetColumnDefCollation(pstate, n, attrtype);
1956 TupleDescInitEntry(tupdesc,
1957 (AttrNumber) i,
1958 attrname,
1959 attrtype,
1960 attrtypmod,
1961 0);
1963 (AttrNumber) i,
1965 rtfunc->funccolnames = lappend(rtfunc->funccolnames,
1967 rtfunc->funccoltypes = lappend_oid(rtfunc->funccoltypes,
1968 attrtype);
1969 rtfunc->funccoltypmods = lappend_int(rtfunc->funccoltypmods,
1970 attrtypmod);
1971 rtfunc->funccolcollations = lappend_oid(rtfunc->funccolcollations,
1973
1974 i++;
1975 }
1976 TupleDescFinalize(tupdesc);
1977
1978 /*
1979 * Ensure that the coldeflist defines a legal set of names (no
1980 * duplicates, but we needn't worry about system column names) and
1981 * datatypes. Although we mostly can't allow pseudo-types, it
1982 * seems safe to allow RECORD and RECORD[], since values within
1983 * those type classes are self-identifying at runtime, and the
1984 * coldeflist doesn't represent anything that will be visible to
1985 * other sessions.
1986 */
1989 }
1990 else
1991 ereport(ERROR,
1993 errmsg("function \"%s\" in FROM has unsupported return type %s",
1995 parser_errposition(pstate, exprLocation(funcexpr))));
1996
1997 /* Finish off the RangeTblFunction and add it to the RTE's list */
1998 rtfunc->funccolcount = tupdesc->natts;
1999 rte->functions = lappend(rte->functions, rtfunc);
2000
2001 /* Save the tupdesc for use below */
2002 functupdescs[funcno] = tupdesc;
2003 totalatts += tupdesc->natts;
2004 funcno++;
2005 }
2006
2007 /*
2008 * If there's more than one function, or we want an ordinality column, we
2009 * have to produce a merged tupdesc.
2010 */
2011 if (nfuncs > 1 || rangefunc->ordinality)
2012 {
2013 if (rangefunc->ordinality)
2014 totalatts++;
2015
2016 /* Disallow more columns than will fit in a tuple */
2018 ereport(ERROR,
2020 errmsg("functions in FROM can return at most %d columns",
2022 parser_errposition(pstate,
2023 exprLocation((Node *) funcexprs))));
2024
2025 /* Merge the tuple descs of each function into a composite one */
2027 natts = 0;
2028 for (i = 0; i < nfuncs; i++)
2029 {
2030 for (j = 1; j <= functupdescs[i]->natts; j++)
2031 TupleDescCopyEntry(tupdesc, ++natts, functupdescs[i], j);
2032 }
2033
2034 /* Add the ordinality column if needed */
2035 if (rangefunc->ordinality)
2036 {
2037 TupleDescInitEntry(tupdesc,
2038 (AttrNumber) ++natts,
2039 "ordinality",
2040 INT8OID,
2041 -1,
2042 0);
2043 /* no need to set collation */
2044 }
2045 TupleDescFinalize(tupdesc);
2046 Assert(natts == totalatts);
2047 }
2048 else
2049 {
2050 /* We can just use the single function's tupdesc as-is */
2051 tupdesc = functupdescs[0];
2052 }
2053
2054 /* Use the tupdesc while assigning column aliases for the RTE */
2055 buildRelationAliases(tupdesc, alias, eref);
2056
2057 /*
2058 * Set flags and access permissions.
2059 *
2060 * Functions are never checked for access rights (at least, not by
2061 * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
2062 */
2063 rte->lateral = lateral;
2064 rte->inFromCl = inFromCl;
2065
2066 /*
2067 * Add completed RTE to pstate's range table list, so that we know its
2068 * index. But we don't add it to the join list --- caller must do that if
2069 * appropriate.
2070 */
2071 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2072
2073 /*
2074 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2075 * list --- caller must do that if appropriate.
2076 */
2078 tupdesc);
2079}
int16 AttrNumber
Definition attnum.h:21
int32_t int32
Definition c.h:676
#define palloc_array(type, count)
Definition fe_memutils.h:91
char * format_type_be(Oid type_oid)
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:299
TypeFuncClass
Definition funcapi.h:147
@ TYPEFUNC_SCALAR
Definition funcapi.h:148
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
@ TYPEFUNC_RECORD
Definition funcapi.h:151
@ TYPEFUNC_COMPOSITE_DOMAIN
Definition funcapi.h:150
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, int flags)
Definition heap.c:453
#define CHKATYPE_ANYRECORD
Definition heap.h:24
#define MaxTupleAttributeNumber
#define MaxHeapAttributeNumber
#define funcname
int j
Definition isn.c:78
char * pstrdup(const char *in)
Definition mcxt.c:1910
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
int exprLocation(const Node *expr)
Definition nodeFuncs.c:1403
static char * chooseScalarFunctionAlias(Node *funcexpr, char *funcname, Alias *alias, int nfuncs)
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition parse_type.c:310
Oid GetColumnDefCollation(ParseState *pstate, const ColumnDef *coldef, Oid typeOid)
Definition parse_type.c:540
@ RTE_FUNCTION
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition pg_list.h:595
#define linitial(l)
Definition pg_list.h:178
unsigned int Oid
char * colname
Definition parsenodes.h:772
TypeName * typeName
Definition parsenodes.h:773
ParseLoc location
Definition parsenodes.h:791
Definition pg_list.h:54
Definition nodes.h:133
bool setof
Definition parsenodes.h:292
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition tupdesc.c:1093
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:909
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
Definition tupdesc.c:472

References Alias::aliasname, Assert, buildNSItemFromTupleDesc(), buildRelationAliases(), CheckAttributeNamesTypes(), CHKATYPE_ANYRECORD, chooseScalarFunctionAlias(), ColumnDef::colname, CreateTemplateTupleDesc(), ereport, errcode(), errmsg, ERROR, exprCollation(), exprLocation(), exprType(), exprTypmod(), fb(), format_type_be(), forthree, RangeTblFunction::funcexpr, funcname, get_expr_result_type(), GetColumnDefCollation(), i, InvalidOid, j, lappend(), lappend_int(), lappend_oid(), lfirst, linitial, list_length(), ColumnDef::location, makeAlias(), makeNode, makeString(), MaxHeapAttributeNumber, MaxTupleAttributeNumber, TupleDescData::natts, NIL, ParseState::p_rtable, palloc_array, parser_errposition(), pstrdup(), RTE_FUNCTION, TypeName::setof, TupleDescCopyEntry(), TupleDescFinalize(), TupleDescInitEntry(), TupleDescInitEntryCollation(), TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, TYPEFUNC_RECORD, TYPEFUNC_SCALAR, ColumnDef::typeName, and typenameTypeIdAndMod().

Referenced by transformRangeFunction().

◆ addRangeTableEntryForGraphTable()

ParseNamespaceItem * addRangeTableEntryForGraphTable ( ParseState pstate,
Oid  graphid,
GraphPattern graph_pattern,
List columns,
List colnames,
Alias alias,
bool  lateral,
bool  inFromCl 
)

Definition at line 2167 of file parse_relation.c.

2175{
2177 char *refname = alias ? alias->aliasname : pstrdup("graph_table");
2178 Alias *eref;
2179 int numaliases;
2180 int varattno;
2181 ListCell *lc;
2182 List *coltypes = NIL;
2183 List *coltypmods = NIL;
2187
2188 Assert(pstate != NULL);
2189
2190 rte->rtekind = RTE_GRAPH_TABLE;
2191 rte->relid = graphid;
2192 rte->relkind = RELKIND_PROPGRAPH;
2193 rte->graph_pattern = graph_pattern;
2194 rte->graph_table_columns = columns;
2195 rte->alias = alias;
2196 rte->rellockmode = AccessShareLock;
2197
2198 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
2199
2200 if (!eref->colnames)
2201 eref->colnames = colnames;
2202
2203 numaliases = list_length(eref->colnames);
2204
2205 /* fill in any unspecified alias columns */
2206 varattno = 0;
2207 foreach(lc, colnames)
2208 {
2209 varattno++;
2210 if (varattno > numaliases)
2211 eref->colnames = lappend(eref->colnames, lfirst(lc));
2212 }
2213 if (varattno < numaliases)
2214 ereport(ERROR,
2216 errmsg("GRAPH_TABLE \"%s\" has %d columns available but %d columns specified",
2217 refname, varattno, numaliases)));
2218
2219 rte->eref = eref;
2220
2221 foreach(lc, columns)
2222 {
2224 Node *colexpr = (Node *) te->expr;
2225
2229 }
2230
2231 /*
2232 * Set flags and access permissions.
2233 */
2234 rte->lateral = lateral;
2235 rte->inFromCl = inFromCl;
2236
2238 perminfo->requiredPerms = ACL_SELECT;
2239
2240 /*
2241 * Add completed RTE to pstate's range table list, so that we know its
2242 * index. But we don't add it to the join list --- caller must do that if
2243 * appropriate.
2244 */
2245 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2246
2247 /*
2248 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2249 * list --- caller must do that if appropriate.
2250 */
2253
2254 nsitem->p_perminfo = perminfo;
2255
2256 return nsitem;
2257}
@ RTE_GRAPH_TABLE
#define lfirst_node(type, lc)
Definition pg_list.h:176
List * colnames
Definition primnodes.h:53
Expr * expr
Definition primnodes.h:2259

References AccessShareLock, ACL_SELECT, addRTEPermissionInfo(), Alias::aliasname, Assert, buildNSItemFromLists(), copyObject, ereport, errcode(), errmsg, ERROR, TargetEntry::expr, exprCollation(), exprType(), exprTypmod(), fb(), lappend(), lappend_int(), lappend_oid(), lfirst, lfirst_node, list_length(), makeAlias(), makeNode, NIL, ParseState::p_rtable, ParseState::p_rteperminfos, pstrdup(), and RTE_GRAPH_TABLE.

Referenced by transformRangeGraphTable().

◆ addRangeTableEntryForGroup()

ParseNamespaceItem * addRangeTableEntryForGroup ( ParseState pstate,
List groupClauses 
)

Definition at line 2698 of file parse_relation.c.

2700{
2702 Alias *eref;
2703 List *groupexprs;
2704 List *coltypes,
2705 *coltypmods,
2707 ListCell *lc;
2709
2710 Assert(pstate != NULL);
2711
2712 rte->rtekind = RTE_GROUP;
2713 rte->alias = NULL;
2714
2715 eref = makeAlias("*GROUP*", NIL);
2716
2717 /* fill in any unspecified alias columns, and extract column type info */
2718 groupexprs = NIL;
2720 foreach(lc, groupClauses)
2721 {
2722 TargetEntry *te = (TargetEntry *) lfirst(lc);
2723 char *colname = te->resname ? pstrdup(te->resname) : "?column?";
2724
2725 eref->colnames = lappend(eref->colnames, makeString(colname));
2726
2727 groupexprs = lappend(groupexprs, copyObject(te->expr));
2728
2730 exprType((Node *) te->expr));
2732 exprTypmod((Node *) te->expr));
2734 exprCollation((Node *) te->expr));
2735 }
2736
2737 rte->eref = eref;
2738 rte->groupexprs = groupexprs;
2739
2740 /*
2741 * Set flags.
2742 *
2743 * The grouping step is never checked for access rights, so no need to
2744 * perform addRTEPermissionInfo().
2745 */
2746 rte->lateral = false;
2747 rte->inFromCl = false;
2748
2749 /*
2750 * Add completed RTE to pstate's range table list, so that we know its
2751 * index. But we don't add it to the join list --- caller must do that if
2752 * appropriate.
2753 */
2754 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2755
2756 /*
2757 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2758 * list --- caller must do that if appropriate.
2759 */
2762
2763 return nsitem;
2764}
@ RTE_GROUP

References Assert, buildNSItemFromLists(), copyObject, TargetEntry::expr, exprCollation(), exprType(), exprTypmod(), fb(), lappend(), lappend_int(), lappend_oid(), lfirst, list_length(), makeAlias(), makeNode, makeString(), NIL, ParseState::p_rtable, pstrdup(), and RTE_GROUP.

Referenced by parseCheckAggregates().

◆ addRangeTableEntryForJoin()

ParseNamespaceItem * addRangeTableEntryForJoin ( ParseState pstate,
List colnames,
ParseNamespaceColumn nscolumns,
JoinType  jointype,
int  nummergedcols,
List aliasvars,
List leftcols,
List rightcols,
Alias join_using_alias,
Alias alias,
bool  inFromCl 
)

Definition at line 2348 of file parse_relation.c.

2359{
2361 Alias *eref;
2362 int numaliases;
2364
2365 Assert(pstate != NULL);
2366
2367 /*
2368 * Fail if join has too many columns --- we must be able to reference any
2369 * of the columns with an AttrNumber.
2370 */
2372 ereport(ERROR,
2374 errmsg("joins can have at most %d columns",
2375 MaxAttrNumber)));
2376
2377 rte->rtekind = RTE_JOIN;
2378 rte->relid = InvalidOid;
2379 rte->subquery = NULL;
2380 rte->jointype = jointype;
2381 rte->joinmergedcols = nummergedcols;
2382 rte->joinaliasvars = aliasvars;
2383 rte->joinleftcols = leftcols;
2384 rte->joinrightcols = rightcols;
2385 rte->join_using_alias = join_using_alias;
2386 rte->alias = alias;
2387
2388 eref = alias ? copyObject(alias) : makeAlias("unnamed_join", NIL);
2389 numaliases = list_length(eref->colnames);
2390
2391 /* fill in any unspecified alias columns */
2392 if (numaliases < list_length(colnames))
2393 eref->colnames = list_concat(eref->colnames,
2394 list_copy_tail(colnames, numaliases));
2395
2396 if (numaliases > list_length(colnames))
2397 ereport(ERROR,
2399 errmsg("join expression \"%s\" has %d columns available but %d columns specified",
2400 eref->aliasname, list_length(colnames), numaliases)));
2401
2402 rte->eref = eref;
2403
2404 /*
2405 * Set flags and access permissions.
2406 *
2407 * Joins are never checked for access rights, so no need to perform
2408 * addRTEPermissionInfo().
2409 */
2410 rte->lateral = false;
2411 rte->inFromCl = inFromCl;
2412
2413 /*
2414 * Add completed RTE to pstate's range table list, so that we know its
2415 * index. But we don't add it to the join list --- caller must do that if
2416 * appropriate.
2417 */
2418 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2419
2420 /*
2421 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2422 * list --- caller must do that if appropriate.
2423 */
2425 nsitem->p_names = rte->eref;
2426 nsitem->p_rte = rte;
2427 nsitem->p_perminfo = NULL;
2428 nsitem->p_rtindex = list_length(pstate->p_rtable);
2429 nsitem->p_nscolumns = nscolumns;
2430 /* set default visibility flags; might get changed later */
2431 nsitem->p_rel_visible = true;
2432 nsitem->p_cols_visible = true;
2433 nsitem->p_lateral_only = false;
2434 nsitem->p_lateral_ok = true;
2435 nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
2436
2437 return nsitem;
2438}
#define MaxAttrNumber
Definition attnum.h:24
#define palloc_object(type)
Definition fe_memutils.h:89
List * list_copy_tail(const List *oldlist, int nskip)
Definition list.c:1613
List * list_concat(List *list1, const List *list2)
Definition list.c:561
@ RTE_JOIN
@ VAR_RETURNING_DEFAULT
Definition primnodes.h:257

References Assert, copyObject, ereport, errcode(), errmsg, ERROR, fb(), InvalidOid, lappend(), list_concat(), list_copy_tail(), list_length(), makeAlias(), makeNode, MaxAttrNumber, NIL, ParseState::p_rtable, palloc_object, RTE_JOIN, and VAR_RETURNING_DEFAULT.

Referenced by transformFromClauseItem(), and transformSetOperationStmt().

◆ addRangeTableEntryForRelation()

ParseNamespaceItem * addRangeTableEntryForRelation ( ParseState pstate,
Relation  rel,
LOCKMODE  lockmode,
Alias alias,
bool  inh,
bool  inFromCl 
)

Definition at line 1604 of file parse_relation.c.

1610{
1613 char *refname = alias ? alias->aliasname : RelationGetRelationName(rel);
1614
1615 Assert(pstate != NULL);
1616
1617 Assert(lockmode == AccessShareLock ||
1618 lockmode == RowShareLock ||
1619 lockmode == RowExclusiveLock);
1620 Assert(CheckRelationLockedByMe(rel, lockmode, true));
1621
1622 rte->rtekind = RTE_RELATION;
1623 rte->alias = alias;
1624 rte->relid = RelationGetRelid(rel);
1625 rte->inh = inh;
1626 rte->relkind = rel->rd_rel->relkind;
1627 rte->rellockmode = lockmode;
1628
1629 /*
1630 * Build the list of effective column names using user-supplied aliases
1631 * and/or actual column names.
1632 */
1633 rte->eref = makeAlias(refname, NIL);
1634 buildRelationAliases(rel->rd_att, alias, rte->eref);
1635
1636 /*
1637 * Set flags and initialize access permissions.
1638 *
1639 * The initial default on access checks is always check-for-READ-access,
1640 * which is the right thing for all except target tables.
1641 */
1642 rte->lateral = false;
1643 rte->inFromCl = inFromCl;
1644
1646 perminfo->requiredPerms = ACL_SELECT;
1647
1648 /*
1649 * Add completed RTE to pstate's range table list, so that we know its
1650 * index. But we don't add it to the join list --- caller must do that if
1651 * appropriate.
1652 */
1653 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1654
1655 /*
1656 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
1657 * list --- caller must do that if appropriate.
1658 */
1660 perminfo, rel->rd_att);
1661}
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition lmgr.c:334
#define RowExclusiveLock
Definition lockdefs.h:38
#define RelationGetRelationName(relation)
Definition rel.h:550

References AccessShareLock, ACL_SELECT, addRTEPermissionInfo(), Alias::aliasname, Assert, buildNSItemFromTupleDesc(), buildRelationAliases(), CheckRelationLockedByMe(), fb(), lappend(), list_length(), makeAlias(), makeNode, NIL, ParseState::p_rtable, ParseState::p_rteperminfos, RelationData::rd_att, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, RowShareLock, and RTE_RELATION.

Referenced by AddRelationNewConstraints(), AlterPolicy(), copy_table(), CreatePolicy(), CreateTriggerFiringOn(), DefineRelation(), DoCopy(), generate_query_for_graph_path(), insert_property_records(), rewriteTargetView(), setTargetTable(), test_rls_hooks_permissive(), test_rls_hooks_restrictive(), transformAlterTableStmt(), transformIndexStmt(), transformOnConflictClause(), transformPartitionSpec(), TransformPubWhereClauses(), transformRuleStmt(), and transformStatsStmt().

◆ addRangeTableEntryForSubquery()

ParseNamespaceItem * addRangeTableEntryForSubquery ( ParseState pstate,
Query subquery,
Alias alias,
bool  lateral,
bool  inFromCl 
)

Definition at line 1675 of file parse_relation.c.

1680{
1682 Alias *eref;
1683 int numaliases;
1684 List *coltypes,
1685 *coltypmods,
1687 int varattno;
1690
1691 Assert(pstate != NULL);
1692
1693 rte->rtekind = RTE_SUBQUERY;
1694 rte->subquery = subquery;
1695 rte->alias = alias;
1696
1697 eref = alias ? copyObject(alias) : makeAlias("unnamed_subquery", NIL);
1698 numaliases = list_length(eref->colnames);
1699
1700 /* fill in any unspecified alias columns, and extract column type info */
1702 varattno = 0;
1703 foreach(tlistitem, subquery->targetList)
1704 {
1706
1707 if (te->resjunk)
1708 continue;
1709 varattno++;
1710 Assert(varattno == te->resno);
1711 if (varattno > numaliases)
1712 {
1713 char *attrname;
1714
1715 attrname = pstrdup(te->resname);
1716 eref->colnames = lappend(eref->colnames, makeString(attrname));
1717 }
1719 exprType((Node *) te->expr));
1721 exprTypmod((Node *) te->expr));
1723 exprCollation((Node *) te->expr));
1724 }
1725 if (varattno < numaliases)
1726 ereport(ERROR,
1728 errmsg("table \"%s\" has %d columns available but %d columns specified",
1729 eref->aliasname, varattno, numaliases)));
1730
1731 rte->eref = eref;
1732
1733 /*
1734 * Set flags.
1735 *
1736 * Subqueries are never checked for access rights, so no need to perform
1737 * addRTEPermissionInfo().
1738 */
1739 rte->lateral = lateral;
1740 rte->inFromCl = inFromCl;
1741
1742 /*
1743 * Add completed RTE to pstate's range table list, so that we know its
1744 * index. But we don't add it to the join list --- caller must do that if
1745 * appropriate.
1746 */
1747 pstate->p_rtable = lappend(pstate->p_rtable, rte);
1748
1749 /*
1750 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
1751 * list --- caller must do that if appropriate.
1752 */
1755
1756 /*
1757 * Mark it visible as a relation name only if it had a user-written alias.
1758 */
1759 nsitem->p_rel_visible = (alias != NULL);
1760
1761 return nsitem;
1762}
@ RTE_SUBQUERY
List * targetList
Definition parsenodes.h:203
AttrNumber resno
Definition primnodes.h:2261

References Assert, buildNSItemFromLists(), copyObject, ereport, errcode(), errmsg, ERROR, TargetEntry::expr, exprCollation(), exprType(), exprTypmod(), fb(), lappend(), lappend_int(), lappend_oid(), lfirst, list_length(), makeAlias(), makeNode, makeString(), NIL, ParseState::p_rtable, pstrdup(), TargetEntry::resno, RTE_SUBQUERY, and Query::targetList.

Referenced by convert_ANY_sublink_to_join(), generate_setop_from_pathqueries(), transformInsertStmt(), transformRangeSubselect(), and transformSetOperationTree().

◆ addRangeTableEntryForTableFunc()

ParseNamespaceItem * addRangeTableEntryForTableFunc ( ParseState pstate,
TableFunc tf,
Alias alias,
bool  lateral,
bool  inFromCl 
)

Definition at line 2088 of file parse_relation.c.

2093{
2095 char *refname;
2096 Alias *eref;
2097 int numaliases;
2098
2099 Assert(pstate != NULL);
2100
2101 /* Disallow more columns than will fit in a tuple */
2102 if (list_length(tf->colnames) > MaxTupleAttributeNumber)
2103 ereport(ERROR,
2105 errmsg("functions in FROM can return at most %d columns",
2107 parser_errposition(pstate,
2108 exprLocation((Node *) tf))));
2109 Assert(list_length(tf->coltypes) == list_length(tf->colnames));
2110 Assert(list_length(tf->coltypmods) == list_length(tf->colnames));
2111 Assert(list_length(tf->colcollations) == list_length(tf->colnames));
2112
2113 rte->rtekind = RTE_TABLEFUNC;
2114 rte->relid = InvalidOid;
2115 rte->subquery = NULL;
2116 rte->tablefunc = tf;
2117 rte->coltypes = tf->coltypes;
2118 rte->coltypmods = tf->coltypmods;
2119 rte->colcollations = tf->colcollations;
2120 rte->alias = alias;
2121
2122 refname = alias ? alias->aliasname :
2123 pstrdup(tf->functype == TFT_XMLTABLE ? "xmltable" : "json_table");
2124 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
2125 numaliases = list_length(eref->colnames);
2126
2127 /* fill in any unspecified alias columns */
2128 if (numaliases < list_length(tf->colnames))
2129 eref->colnames = list_concat(eref->colnames,
2130 list_copy_tail(tf->colnames, numaliases));
2131
2132 if (numaliases > list_length(tf->colnames))
2133 ereport(ERROR,
2135 errmsg("%s function has %d columns available but %d columns specified",
2136 tf->functype == TFT_XMLTABLE ? "XMLTABLE" : "JSON_TABLE",
2137 list_length(tf->colnames), numaliases)));
2138
2139 rte->eref = eref;
2140
2141 /*
2142 * Set flags and access permissions.
2143 *
2144 * Tablefuncs are never checked for access rights (at least, not by
2145 * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
2146 */
2147 rte->lateral = lateral;
2148 rte->inFromCl = inFromCl;
2149
2150 /*
2151 * Add completed RTE to pstate's range table list, so that we know its
2152 * index. But we don't add it to the join list --- caller must do that if
2153 * appropriate.
2154 */
2155 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2156
2157 /*
2158 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2159 * list --- caller must do that if appropriate.
2160 */
2162 rte->coltypes, rte->coltypmods,
2163 rte->colcollations);
2164}
@ RTE_TABLEFUNC
@ TFT_XMLTABLE
Definition primnodes.h:101
TableFuncType functype
Definition primnodes.h:115

References Alias::aliasname, Assert, buildNSItemFromLists(), copyObject, ereport, errcode(), errmsg, ERROR, exprLocation(), fb(), TableFunc::functype, InvalidOid, lappend(), list_concat(), list_copy_tail(), list_length(), makeAlias(), makeNode, MaxTupleAttributeNumber, NIL, ParseState::p_rtable, parser_errposition(), pstrdup(), RTE_TABLEFUNC, and TFT_XMLTABLE.

Referenced by transformJsonTable(), and transformRangeTableFunc().

◆ addRangeTableEntryForValues()

ParseNamespaceItem * addRangeTableEntryForValues ( ParseState pstate,
List exprs,
List coltypes,
List coltypmods,
List colcollations,
Alias alias,
bool  lateral,
bool  inFromCl 
)

Definition at line 2266 of file parse_relation.c.

2274{
2276 char *refname = alias ? alias->aliasname : pstrdup("*VALUES*");
2277 Alias *eref;
2278 int numaliases;
2279 int numcolumns;
2280
2281 Assert(pstate != NULL);
2282
2283 rte->rtekind = RTE_VALUES;
2284 rte->relid = InvalidOid;
2285 rte->subquery = NULL;
2286 rte->values_lists = exprs;
2287 rte->coltypes = coltypes;
2288 rte->coltypmods = coltypmods;
2289 rte->colcollations = colcollations;
2290 rte->alias = alias;
2291
2292 eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
2293
2294 /* fill in any unspecified alias columns */
2295 numcolumns = list_length((List *) linitial(exprs));
2296 numaliases = list_length(eref->colnames);
2297 while (numaliases < numcolumns)
2298 {
2299 char attrname[64];
2300
2301 numaliases++;
2302 snprintf(attrname, sizeof(attrname), "column%d", numaliases);
2303 eref->colnames = lappend(eref->colnames,
2305 }
2306 if (numcolumns < numaliases)
2307 ereport(ERROR,
2309 errmsg("VALUES lists \"%s\" have %d columns available but %d columns specified",
2310 refname, numcolumns, numaliases)));
2311
2312 rte->eref = eref;
2313
2314 /*
2315 * Set flags and access permissions.
2316 *
2317 * Subqueries are never checked for access rights, so no need to perform
2318 * addRTEPermissionInfo().
2319 */
2320 rte->lateral = lateral;
2321 rte->inFromCl = inFromCl;
2322
2323 /*
2324 * Add completed RTE to pstate's range table list, so that we know its
2325 * index. But we don't add it to the join list --- caller must do that if
2326 * appropriate.
2327 */
2328 pstate->p_rtable = lappend(pstate->p_rtable, rte);
2329
2330 /*
2331 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
2332 * list --- caller must do that if appropriate.
2333 */
2335 rte->coltypes, rte->coltypmods,
2336 rte->colcollations);
2337}
@ RTE_VALUES
#define snprintf
Definition port.h:261

References Alias::aliasname, Assert, buildNSItemFromLists(), copyObject, ereport, errcode(), errmsg, ERROR, fb(), InvalidOid, lappend(), linitial, list_length(), makeAlias(), makeNode, makeString(), NIL, ParseState::p_rtable, pstrdup(), RTE_VALUES, and snprintf.

Referenced by transformInsertStmt(), and transformValuesClause().

◆ addRTEPermissionInfo()

RTEPermissionInfo * addRTEPermissionInfo ( List **  rteperminfos,
RangeTblEntry rte 
)

Definition at line 4051 of file parse_relation.c.

4052{
4054
4055 Assert(OidIsValid(rte->relid));
4056 Assert(rte->perminfoindex == 0);
4057
4058 /* Nope, so make one and add to the list. */
4060 perminfo->relid = rte->relid;
4061 perminfo->inh = rte->inh;
4062 /* Other information is set by fetching the node as and where needed. */
4063
4064 *rteperminfos = lappend(*rteperminfos, perminfo);
4065
4066 /* Note its index (1-based!) */
4067 rte->perminfoindex = list_length(*rteperminfos);
4068
4069 return perminfo;
4070}
#define OidIsValid(objectId)
Definition c.h:914

References Assert, fb(), lappend(), list_length(), makeNode, and OidIsValid.

Referenced by add_rte_to_flat_rtable(), addRangeTableEntry(), addRangeTableEntryForGraphTable(), addRangeTableEntryForRelation(), create_edata_for_relation(), create_estate_for_relation(), plan_cluster_use_sort(), plan_create_index_workers(), and rewriteTargetView().

◆ attnameAttNum()

int attnameAttNum ( Relation  rd,
const char attname,
bool  sysColOK 
)

Definition at line 3706 of file parse_relation.c.

3707{
3708 int i;
3709
3710 for (i = 0; i < RelationGetNumberOfAttributes(rd); i++)
3711 {
3712 Form_pg_attribute att = TupleDescAttr(rd->rd_att, i);
3713
3714 if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped)
3715 return i + 1;
3716 }
3717
3718 if (sysColOK)
3719 {
3721 return i;
3722 }
3723
3724 /* on failure */
3725 return InvalidAttrNumber;
3726}
#define InvalidAttrNumber
Definition attnum.h:23
int namestrcmp(Name name, const char *str)
Definition name.c:247
static int specialAttNum(const char *attname)
NameData attname
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:522

References attname, fb(), i, InvalidAttrNumber, namestrcmp(), RelationGetNumberOfAttributes, specialAttNum(), and TupleDescAttr().

Referenced by checkInsertTargets(), CreateTriggerFiringOn(), do_analyze_rel(), transformForPortionOfClause(), transformUpdateTargetList(), and validate_va_cols_list().

◆ attnumAttName()

const NameData * attnumAttName ( Relation  rd,
int  attid 
)

Definition at line 3757 of file parse_relation.c.

3758{
3759 if (attid <= 0)
3760 {
3762
3764 return &sysatt->attname;
3765 }
3766 if (attid > rd->rd_att->natts)
3767 elog(ERROR, "invalid attribute number %d", attid);
3768 return &TupleDescAttr(rd->rd_att, attid - 1)->attname;
3769}
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition heap.c:236
FormData_pg_attribute

References elog, ERROR, fb(), FormData_pg_attribute, SystemAttributeDefinition(), and TupleDescAttr().

Referenced by transformFkeyGetPrimaryKey().

◆ attnumCollationId()

Oid attnumCollationId ( Relation  rd,
int  attid 
)

Definition at line 3799 of file parse_relation.c.

3800{
3801 if (attid <= 0)
3802 {
3803 /* All system attributes are of noncollatable types. */
3804 return InvalidOid;
3805 }
3806 if (attid > rd->rd_att->natts)
3807 elog(ERROR, "invalid attribute number %d", attid);
3808 return TupleDescAttr(rd->rd_att, attid - 1)->attcollation;
3809}

References elog, ERROR, fb(), InvalidOid, and TupleDescAttr().

Referenced by transformFkeyGetPrimaryKey().

◆ attnumTypeId()

Oid attnumTypeId ( Relation  rd,
int  attid 
)

Definition at line 3779 of file parse_relation.c.

3780{
3781 if (attid <= 0)
3782 {
3784
3786 return sysatt->atttypid;
3787 }
3788 if (attid > rd->rd_att->natts)
3789 elog(ERROR, "invalid attribute number %d", attid);
3790 return TupleDescAttr(rd->rd_att, attid - 1)->atttypid;
3791}

References elog, ERROR, fb(), FormData_pg_attribute, SystemAttributeDefinition(), and TupleDescAttr().

Referenced by transformAssignedExpr(), and transformFkeyGetPrimaryKey().

◆ buildNSItemFromLists()

static ParseNamespaceItem * buildNSItemFromLists ( RangeTblEntry rte,
Index  rtindex,
List coltypes,
List coltypmods,
List colcollations 
)
static

Definition at line 1398 of file parse_relation.c.

1400{
1404 int varattno;
1405 ListCell *lct;
1406 ListCell *lcm;
1407 ListCell *lcc;
1408
1409 /* colnames must have the same number of entries as the nsitem */
1410 Assert(maxattrs == list_length(rte->eref->colnames));
1411
1414
1415 /* extract per-column data from the lists */
1418
1419 varattno = 0;
1421 lcm, coltypmods,
1423 {
1424 nscolumns[varattno].p_varno = rtindex;
1425 nscolumns[varattno].p_varattno = varattno + 1;
1426 nscolumns[varattno].p_vartype = lfirst_oid(lct);
1427 nscolumns[varattno].p_vartypmod = lfirst_int(lcm);
1428 nscolumns[varattno].p_varcollid = lfirst_oid(lcc);
1429 nscolumns[varattno].p_varnosyn = rtindex;
1430 nscolumns[varattno].p_varattnosyn = varattno + 1;
1431 varattno++;
1432 }
1433
1434 /* ... and build the nsitem */
1436 nsitem->p_names = rte->eref;
1437 nsitem->p_rte = rte;
1438 nsitem->p_rtindex = rtindex;
1439 nsitem->p_perminfo = NULL;
1440 nsitem->p_nscolumns = nscolumns;
1441 /* set default visibility flags; might get changed later */
1442 nsitem->p_rel_visible = true;
1443 nsitem->p_cols_visible = true;
1444 nsitem->p_lateral_only = false;
1445 nsitem->p_lateral_ok = true;
1446 nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
1447
1448 return nsitem;
1449}
void * palloc0(Size size)
Definition mcxt.c:1420
#define lfirst_int(lc)
Definition pg_list.h:173
#define lfirst_oid(lc)
Definition pg_list.h:174

References Assert, fb(), forthree, lfirst_int, lfirst_oid, list_length(), palloc0(), palloc_object, and VAR_RETURNING_DEFAULT.

Referenced by addRangeTableEntryForCTE(), addRangeTableEntryForGraphTable(), addRangeTableEntryForGroup(), addRangeTableEntryForSubquery(), addRangeTableEntryForTableFunc(), and addRangeTableEntryForValues().

◆ buildNSItemFromTupleDesc()

static ParseNamespaceItem * buildNSItemFromTupleDesc ( RangeTblEntry rte,
Index  rtindex,
RTEPermissionInfo perminfo,
TupleDesc  tupdesc 
)
static

Definition at line 1337 of file parse_relation.c.

1340{
1343 int maxattrs = tupdesc->natts;
1344 int varattno;
1345
1346 /* colnames must have the same number of entries as the nsitem */
1347 Assert(maxattrs == list_length(rte->eref->colnames));
1348
1349 /* extract per-column data from the tupdesc */
1352
1353 for (varattno = 0; varattno < maxattrs; varattno++)
1354 {
1355 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
1356
1357 /* For a dropped column, just leave the entry as zeroes */
1358 if (attr->attisdropped)
1359 continue;
1360
1361 nscolumns[varattno].p_varno = rtindex;
1362 nscolumns[varattno].p_varattno = varattno + 1;
1363 nscolumns[varattno].p_vartype = attr->atttypid;
1364 nscolumns[varattno].p_vartypmod = attr->atttypmod;
1365 nscolumns[varattno].p_varcollid = attr->attcollation;
1366 nscolumns[varattno].p_varnosyn = rtindex;
1367 nscolumns[varattno].p_varattnosyn = varattno + 1;
1368 }
1369
1370 /* ... and build the nsitem */
1372 nsitem->p_names = rte->eref;
1373 nsitem->p_rte = rte;
1374 nsitem->p_rtindex = rtindex;
1375 nsitem->p_perminfo = perminfo;
1376 nsitem->p_nscolumns = nscolumns;
1377 /* set default visibility flags; might get changed later */
1378 nsitem->p_rel_visible = true;
1379 nsitem->p_cols_visible = true;
1380 nsitem->p_lateral_only = false;
1381 nsitem->p_lateral_ok = true;
1382 nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
1383
1384 return nsitem;
1385}

References Assert, fb(), list_length(), TupleDescData::natts, palloc0(), palloc_object, TupleDescAttr(), and VAR_RETURNING_DEFAULT.

Referenced by addRangeTableEntry(), addRangeTableEntryForENR(), addRangeTableEntryForFunction(), and addRangeTableEntryForRelation().

◆ buildRelationAliases()

static void buildRelationAliases ( TupleDesc  tupdesc,
Alias alias,
Alias eref 
)
static

Definition at line 1220 of file parse_relation.c.

1221{
1222 int maxattrs = tupdesc->natts;
1223 List *aliaslist;
1225 int numaliases;
1226 int varattno;
1227 int numdropped = 0;
1228
1229 Assert(eref->colnames == NIL);
1230
1231 if (alias)
1232 {
1233 aliaslist = alias->colnames;
1236 /* We'll rebuild the alias colname list */
1237 alias->colnames = NIL;
1238 }
1239 else
1240 {
1241 aliaslist = NIL;
1242 aliaslc = NULL;
1243 numaliases = 0;
1244 }
1245
1246 for (varattno = 0; varattno < maxattrs; varattno++)
1247 {
1248 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
1250
1251 if (attr->attisdropped)
1252 {
1253 /* Always insert an empty string for a dropped column */
1255 if (aliaslc)
1256 alias->colnames = lappend(alias->colnames, attrname);
1257 numdropped++;
1258 }
1259 else if (aliaslc)
1260 {
1261 /* Use the next user-supplied alias */
1264 alias->colnames = lappend(alias->colnames, attrname);
1265 }
1266 else
1267 {
1268 attrname = makeString(pstrdup(NameStr(attr->attname)));
1269 /* we're done with the alias if any */
1270 }
1271
1272 eref->colnames = lappend(eref->colnames, attrname);
1273 }
1274
1275 /* Too many user-supplied aliases? */
1276 if (aliaslc)
1277 ereport(ERROR,
1279 errmsg("table \"%s\" has %d columns available but %d columns specified",
1280 eref->aliasname, maxattrs - numdropped, numaliases)));
1281}
#define NameStr(name)
Definition c.h:891
static ListCell * list_head(const List *l)
Definition pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:375
Definition value.h:64

References Assert, Alias::colnames, ereport, errcode(), errmsg, ERROR, fb(), lappend(), lfirst_node, list_head(), list_length(), lnext(), makeString(), NameStr, TupleDescData::natts, NIL, pstrdup(), and TupleDescAttr().

Referenced by addRangeTableEntry(), addRangeTableEntryForENR(), addRangeTableEntryForFunction(), and addRangeTableEntryForRelation().

◆ check_lateral_ref_ok()

static void check_lateral_ref_ok ( ParseState pstate,
ParseNamespaceItem nsitem,
int  location 
)
static

Definition at line 487 of file parse_relation.c.

489{
490 if (nsitem->p_lateral_only && !nsitem->p_lateral_ok)
491 {
492 /* SQL:2008 demands this be an error, not an invisible item */
493 RangeTblEntry *rte = nsitem->p_rte;
494 char *refname = nsitem->p_names->aliasname;
495
498 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
499 refname),
500 (pstate->p_target_nsitem != NULL &&
501 rte == pstate->p_target_nsitem->p_rte) ?
502 errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
503 refname) :
504 errdetail("The combining JOIN type must be INNER or LEFT for a LATERAL reference."),
505 parser_errposition(pstate, location)));
506 }
507}
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
RangeTblEntry * p_rte
Definition parse_node.h:315
ParseNamespaceItem * p_target_nsitem
Definition parse_node.h:229

References ereport, errcode(), errdetail(), errhint(), errmsg, ERROR, fb(), ParseNamespaceItem::p_rte, ParseState::p_target_nsitem, and parser_errposition().

Referenced by colNameToVar(), scanNameSpaceForRefname(), and scanNameSpaceForRelid().

◆ checkNameSpaceConflicts()

void checkNameSpaceConflicts ( ParseState pstate,
List namespace1,
List namespace2 
)

Definition at line 438 of file parse_relation.c.

440{
441 ListCell *l1;
442
443 foreach(l1, namespace1)
444 {
446 RangeTblEntry *rte1 = nsitem1->p_rte;
447 const char *aliasname1 = nsitem1->p_names->aliasname;
448 ListCell *l2;
449
450 if (!nsitem1->p_rel_visible)
451 continue;
452
453 foreach(l2, namespace2)
454 {
456 RangeTblEntry *rte2 = nsitem2->p_rte;
457 const char *aliasname2 = nsitem2->p_names->aliasname;
458
459 if (!nsitem2->p_rel_visible)
460 continue;
461 if (strcmp(aliasname2, aliasname1) != 0)
462 continue; /* definitely no conflict */
463 if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
464 rte2->rtekind == RTE_RELATION && rte2->alias == NULL &&
465 rte1->relid != rte2->relid)
466 continue; /* no conflict per SQL rule */
469 errmsg("table name \"%s\" specified more than once",
470 aliasname1)));
471 }
472 }
473}

References ereport, errcode(), errmsg, ERROR, fb(), lfirst, and RTE_RELATION.

Referenced by transformFromClause(), and transformFromClauseItem().

◆ chooseScalarFunctionAlias()

static char * chooseScalarFunctionAlias ( Node funcexpr,
char funcname,
Alias alias,
int  nfuncs 
)
static

Definition at line 1297 of file parse_relation.c.

1299{
1300 char *pname;
1301
1302 /*
1303 * If the expression is a simple function call, and the function has a
1304 * single OUT parameter that is named, use the parameter's name.
1305 */
1306 if (funcexpr && IsA(funcexpr, FuncExpr))
1307 {
1308 pname = get_func_result_name(((FuncExpr *) funcexpr)->funcid);
1309 if (pname)
1310 return pname;
1311 }
1312
1313 /*
1314 * If there's just one function in the RTE, and the user gave an RTE alias
1315 * name, use that name. (This makes FROM func() AS foo use "foo" as the
1316 * column name as well as the table alias.)
1317 */
1318 if (nfuncs == 1 && alias)
1319 return alias->aliasname;
1320
1321 /*
1322 * Otherwise use the function name.
1323 */
1324 return funcname;
1325}
char * get_func_result_name(Oid functionId)
Definition funcapi.c:1610

References Alias::aliasname, fb(), funcname, get_func_result_name(), and IsA.

Referenced by addRangeTableEntryForFunction().

◆ colNameToVar()

Node * colNameToVar ( ParseState pstate,
const char colname,
bool  localonly,
int  location 
)

Definition at line 926 of file parse_relation.c.

928{
929 Node *result = NULL;
930 int sublevels_up = 0;
931 ParseState *orig_pstate = pstate;
932
933 while (pstate != NULL)
934 {
935 ListCell *l;
936
937 foreach(l, pstate->p_namespace)
938 {
941
942 /* Ignore table-only items */
943 if (!nsitem->p_cols_visible)
944 continue;
945 /* If not inside LATERAL, ignore lateral-only items */
946 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
947 continue;
948
949 /* use orig_pstate here for consistency with other callers */
951 colname, location);
952
953 if (newresult)
954 {
955 if (result)
958 errmsg("column reference \"%s\" is ambiguous",
959 colname),
960 parser_errposition(pstate, location)));
961 check_lateral_ref_ok(pstate, nsitem, location);
963 }
964 }
965
966 if (result != NULL || localonly)
967 break; /* found, or don't want to look at parent */
968
969 pstate = pstate->parentParseState;
970 sublevels_up++;
971 }
972
973 return result;
974}
uint32 result
Node * scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, const char *colname, int location)
static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem, int location)
ParseState * parentParseState
Definition parse_node.h:213
bool p_lateral_active
Definition parse_node.h:224

References check_lateral_ref_ok(), ereport, errcode(), errmsg, ERROR, fb(), lfirst, ParseState::p_lateral_active, ParseState::p_namespace, ParseState::parentParseState, parser_errposition(), result, and scanNSItemForColumn().

Referenced by findTargetlistEntrySQL92(), and transformColumnRef().

◆ errorMissingColumn()

void errorMissingColumn ( ParseState pstate,
const char relname,
const char colname,
int  location 
)

Definition at line 3889 of file parse_relation.c.

3891{
3893
3894 /*
3895 * Search the entire rtable looking for possible matches. If we find one,
3896 * emit a hint about it.
3897 */
3898 state = searchRangeTableForCol(pstate, relname, colname, location);
3899
3900 /*
3901 * If there are exact match(es), they must be inaccessible for some
3902 * reason.
3903 */
3904 if (state->rexact1)
3905 {
3906 /*
3907 * We don't try too hard when there's multiple inaccessible exact
3908 * matches, but at least be sure that we don't misleadingly suggest
3909 * that there's only one.
3910 */
3911 if (state->rexact2)
3912 ereport(ERROR,
3914 relname ?
3915 errmsg("column %s.%s does not exist", relname, colname) :
3916 errmsg("column \"%s\" does not exist", colname),
3917 errdetail("There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query.",
3918 colname),
3919 !relname ? errhint("Try using a table-qualified name.") : 0,
3920 parser_errposition(pstate, location)));
3921 /* Single exact match, so try to determine why it's inaccessible. */
3922 ereport(ERROR,
3924 relname ?
3925 errmsg("column %s.%s does not exist", relname, colname) :
3926 errmsg("column \"%s\" does not exist", colname),
3927 errdetail("There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query.",
3928 colname, state->rexact1->eref->aliasname),
3929 rte_visible_if_lateral(pstate, state->rexact1) ?
3930 errhint("To reference that column, you must mark this subquery with LATERAL.") :
3931 (!relname && rte_visible_if_qualified(pstate, state->rexact1)) ?
3932 errhint("To reference that column, you must use a table-qualified name.") : 0,
3933 parser_errposition(pstate, location)));
3934 }
3935
3936 if (!state->rsecond)
3937 {
3938 /* If we found no match at all, we have little to report */
3939 if (!state->rfirst)
3940 ereport(ERROR,
3942 relname ?
3943 errmsg("column %s.%s does not exist", relname, colname) :
3944 errmsg("column \"%s\" does not exist", colname),
3945 parser_errposition(pstate, location)));
3946 /* Handle case where we have a single alternative spelling to offer */
3947 ereport(ERROR,
3949 relname ?
3950 errmsg("column %s.%s does not exist", relname, colname) :
3951 errmsg("column \"%s\" does not exist", colname),
3952 errhint("Perhaps you meant to reference the column \"%s.%s\".",
3953 state->rfirst->eref->aliasname,
3954 strVal(list_nth(state->rfirst->eref->colnames,
3955 state->first - 1))),
3956 parser_errposition(pstate, location)));
3957 }
3958 else
3959 {
3960 /* Handle case where there are two equally useful column hints */
3961 ereport(ERROR,
3963 relname ?
3964 errmsg("column %s.%s does not exist", relname, colname) :
3965 errmsg("column \"%s\" does not exist", colname),
3966 errhint("Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\".",
3967 state->rfirst->eref->aliasname,
3968 strVal(list_nth(state->rfirst->eref->colnames,
3969 state->first - 1)),
3970 state->rsecond->eref->aliasname,
3971 strVal(list_nth(state->rsecond->eref->colnames,
3972 state->second - 1))),
3973 parser_errposition(pstate, location)));
3974 }
3975}
static bool rte_visible_if_lateral(ParseState *pstate, RangeTblEntry *rte)
static FuzzyAttrMatchState * searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colname, int location)
static bool rte_visible_if_qualified(ParseState *pstate, RangeTblEntry *rte)
NameData relname
Definition pg_class.h:40
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define strVal(v)
Definition value.h:82

References ereport, errcode(), errdetail(), errhint(), errmsg, ERROR, fb(), list_nth(), parser_errposition(), relname, rte_visible_if_lateral(), rte_visible_if_qualified(), searchRangeTableForCol(), and strVal.

Referenced by transformColumnRef().

◆ errorMissingRTE()

void errorMissingRTE ( ParseState pstate,
RangeVar relation 
)

Definition at line 3818 of file parse_relation.c.

3819{
3821 const char *badAlias = NULL;
3822
3823 /*
3824 * Check to see if there are any potential matches in the query's
3825 * rangetable. (Note: cases involving a bad schema name in the RangeVar
3826 * will throw error immediately here. That seems OK.)
3827 */
3828 rte = searchRangeTableForRel(pstate, relation);
3829
3830 /*
3831 * If we found a match that has an alias and the alias is visible in the
3832 * namespace, then the problem is probably use of the relation's real name
3833 * instead of its alias, ie "SELECT foo.* FROM foo f". This mistake is
3834 * common enough to justify a specific hint.
3835 *
3836 * If we found a match that doesn't meet those criteria, assume the
3837 * problem is illegal use of a relation outside its scope, as in the
3838 * MySQL-ism "SELECT ... FROM a, b LEFT JOIN c ON (a.x = c.y)".
3839 */
3840 if (rte && rte->alias &&
3841 strcmp(rte->eref->aliasname, relation->relname) != 0)
3842 {
3844 int sublevels_up;
3845
3846 nsitem = refnameNamespaceItem(pstate, NULL, rte->eref->aliasname,
3847 relation->location,
3848 &sublevels_up);
3849 if (nsitem && nsitem->p_rte == rte)
3850 badAlias = rte->eref->aliasname;
3851 }
3852
3853 /* If it looks like the user forgot to use an alias, hint about that */
3854 if (badAlias)
3855 ereport(ERROR,
3857 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
3858 relation->relname),
3859 errhint("Perhaps you meant to reference the table alias \"%s\".",
3860 badAlias),
3861 parser_errposition(pstate, relation->location)));
3862 /* Hint about case where we found an (inaccessible) exact match */
3863 else if (rte)
3864 ereport(ERROR,
3866 errmsg("invalid reference to FROM-clause entry for table \"%s\"",
3867 relation->relname),
3868 errdetail("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
3869 rte->eref->aliasname),
3870 rte_visible_if_lateral(pstate, rte) ?
3871 errhint("To reference that table, you must mark this subquery with LATERAL.") : 0,
3872 parser_errposition(pstate, relation->location)));
3873 /* Else, we have nothing to offer but the bald statement of error */
3874 else
3875 ereport(ERROR,
3877 errmsg("missing FROM-clause entry for table \"%s\"",
3878 relation->relname),
3879 parser_errposition(pstate, relation->location)));
3880}
static RangeTblEntry * searchRangeTableForRel(ParseState *pstate, RangeVar *relation)
ParseNamespaceItem * refnameNamespaceItem(ParseState *pstate, const char *schemaname, const char *refname, int location, int *sublevels_up)
#define ERRCODE_UNDEFINED_TABLE
Definition pgbench.c:79

References ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errdetail(), errhint(), errmsg, ERROR, fb(), RangeVar::location, parser_errposition(), refnameNamespaceItem(), RangeVar::relname, rte_visible_if_lateral(), and searchRangeTableForRel().

Referenced by ExpandColumnRefStar(), and transformColumnRef().

◆ expandNSItemAttrs()

List * expandNSItemAttrs ( ParseState pstate,
ParseNamespaceItem nsitem,
int  sublevels_up,
bool  require_col_privs,
int  location 
)

Definition at line 3408 of file parse_relation.c.

3410{
3411 RangeTblEntry *rte = nsitem->p_rte;
3412 RTEPermissionInfo *perminfo = nsitem->p_perminfo;
3413 List *names,
3414 *vars;
3415 ListCell *name,
3416 *var;
3417 List *te_list = NIL;
3418
3419 vars = expandNSItemVars(pstate, nsitem, sublevels_up, location, &names);
3420
3421 /*
3422 * Require read access to the table. This is normally redundant with the
3423 * markVarForSelectPriv calls below, but not if the table has zero
3424 * columns. We need not do anything if the nsitem is for a join: its
3425 * component tables will have been marked ACL_SELECT when they were added
3426 * to the rangetable. (This step changes things only for the target
3427 * relation of UPDATE/DELETE, which cannot be under a join.)
3428 */
3429 if (rte->rtekind == RTE_RELATION)
3430 {
3431 Assert(perminfo != NULL);
3432 perminfo->requiredPerms |= ACL_SELECT;
3433 }
3434
3435 forboth(name, names, var, vars)
3436 {
3437 char *label = strVal(lfirst(name));
3438 Var *varnode = (Var *) lfirst(var);
3439 TargetEntry *te;
3440
3441 te = makeTargetEntry((Expr *) varnode,
3442 (AttrNumber) pstate->p_next_resno++,
3443 label,
3444 false);
3445 te_list = lappend(te_list, te);
3446
3448 {
3449 /* Require read access to each column */
3451 }
3452 }
3453
3454 Assert(name == NULL && var == NULL); /* lists not the same length? */
3455
3456 return te_list;
3457}
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition makefuncs.c:289
void markVarForSelectPriv(ParseState *pstate, Var *var)
List * expandNSItemVars(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, int location, List **colnames)
static char * label
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:550
int p_next_resno
Definition parse_node.h:233
const char * name

References ACL_SELECT, Assert, expandNSItemVars(), fb(), forboth, label, lappend(), lfirst, makeTargetEntry(), markVarForSelectPriv(), name, NIL, ParseState::p_next_resno, RTE_RELATION, and strVal.

Referenced by ExpandAllTables(), ExpandSingleTable(), and transformValuesClause().

◆ expandNSItemVars()

List * expandNSItemVars ( ParseState pstate,
ParseNamespaceItem nsitem,
int  sublevels_up,
int  location,
List **  colnames 
)

Definition at line 3343 of file parse_relation.c.

3346{
3347 List *result = NIL;
3348 int colindex;
3349 ListCell *lc;
3350
3351 if (colnames)
3352 *colnames = NIL;
3353 colindex = 0;
3354 foreach(lc, nsitem->p_names->colnames)
3355 {
3357 const char *colname = strVal(colnameval);
3358 ParseNamespaceColumn *nscol = nsitem->p_nscolumns + colindex;
3359
3360 if (nscol->p_dontexpand)
3361 {
3362 /* skip */
3363 }
3364 else if (colname[0])
3365 {
3366 Var *var;
3367
3368 Assert(nscol->p_varno > 0);
3369 var = makeVar(nscol->p_varno,
3370 nscol->p_varattno,
3371 nscol->p_vartype,
3372 nscol->p_vartypmod,
3373 nscol->p_varcollid,
3374 sublevels_up);
3375 /* makeVar doesn't offer parameters for these, so set by hand: */
3376 var->varreturningtype = nscol->p_varreturningtype;
3377 var->varnosyn = nscol->p_varnosyn;
3378 var->varattnosyn = nscol->p_varattnosyn;
3379 var->location = location;
3380
3381 /* ... and update varnullingrels */
3382 markNullableIfNeeded(pstate, var);
3383
3384 result = lappend(result, var);
3385 if (colnames)
3386 *colnames = lappend(*colnames, colnameval);
3387 }
3388 else
3389 {
3390 /* dropped column, ignore */
3391 Assert(nscol->p_varno == 0);
3392 }
3393 colindex++;
3394 }
3395 return result;
3396}
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition makefuncs.c:66
void markNullableIfNeeded(ParseState *pstate, Var *var)
ParseLoc location
Definition primnodes.h:311
VarReturningType varreturningtype
Definition primnodes.h:298

References Assert, fb(), lappend(), lfirst, Var::location, makeVar(), markNullableIfNeeded(), NIL, result, strVal, and Var::varreturningtype.

Referenced by coerce_record_to_complex(), expandNSItemAttrs(), ExpandSingleTable(), and transformInsertStmt().

◆ expandRelation()

static void expandRelation ( Oid  relid,
Alias eref,
int  rtindex,
int  sublevels_up,
VarReturningType  returning_type,
int  location,
bool  include_dropped,
List **  colnames,
List **  colvars 
)
static

Definition at line 3234 of file parse_relation.c.

3238{
3239 Relation rel;
3240
3241 /* Get the tupledesc and turn it over to expandTupleDesc */
3242 rel = relation_open(relid, AccessShareLock);
3243 expandTupleDesc(rel->rd_att, eref, rel->rd_att->natts, 0,
3244 rtindex, sublevels_up, returning_type,
3245 location, include_dropped,
3246 colnames, colvars);
3248}
static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:48

References AccessShareLock, expandTupleDesc(), fb(), TupleDescData::natts, RelationData::rd_att, relation_close(), and relation_open().

Referenced by expandRTE().

◆ expandRTE()

void expandRTE ( RangeTblEntry rte,
int  rtindex,
int  sublevels_up,
VarReturningType  returning_type,
int  location,
bool  include_dropped,
List **  colnames,
List **  colvars 
)

Definition at line 2866 of file parse_relation.c.

2870{
2871 int varattno;
2872
2873 if (colnames)
2874 *colnames = NIL;
2875 if (colvars)
2876 *colvars = NIL;
2877
2878 switch (rte->rtekind)
2879 {
2880 case RTE_RELATION:
2881 /* Ordinary relation RTE */
2882 expandRelation(rte->relid, rte->eref,
2883 rtindex, sublevels_up, returning_type, location,
2884 include_dropped, colnames, colvars);
2885 break;
2886 case RTE_SUBQUERY:
2887 {
2888 /* Subquery RTE */
2889 ListCell *aliasp_item = list_head(rte->eref->colnames);
2891
2892 varattno = 0;
2893 foreach(tlistitem, rte->subquery->targetList)
2894 {
2896
2897 if (te->resjunk)
2898 continue;
2899 varattno++;
2900 Assert(varattno == te->resno);
2901
2902 /*
2903 * Formerly it was possible for the subquery tlist to have
2904 * more non-junk entries than the colnames list does (if
2905 * this RTE has been expanded from a view that has more
2906 * columns than it did when the current query was parsed).
2907 * Now that ApplyRetrieveRule cleans up such cases, we
2908 * shouldn't see that anymore, but let's just check.
2909 */
2910 if (!aliasp_item)
2911 elog(ERROR, "too few column names for subquery %s",
2912 rte->eref->aliasname);
2913
2914 if (colnames)
2915 {
2916 char *label = strVal(lfirst(aliasp_item));
2917
2918 *colnames = lappend(*colnames, makeString(pstrdup(label)));
2919 }
2920
2921 if (colvars)
2922 {
2923 Var *varnode;
2924
2925 varnode = makeVar(rtindex, varattno,
2926 exprType((Node *) te->expr),
2927 exprTypmod((Node *) te->expr),
2928 exprCollation((Node *) te->expr),
2929 sublevels_up);
2930 varnode->varreturningtype = returning_type;
2931 varnode->location = location;
2932
2934 }
2935
2936 aliasp_item = lnext(rte->eref->colnames, aliasp_item);
2937 }
2938 }
2939 break;
2940 case RTE_FUNCTION:
2941 {
2942 /* Function RTE */
2943 int atts_done = 0;
2944 ListCell *lc;
2945
2946 foreach(lc, rte->functions)
2947 {
2951 TupleDesc tupdesc = NULL;
2952
2953 /* If it has a coldeflist, it returns RECORD */
2954 if (rtfunc->funccolnames != NIL)
2956 else
2958 &funcrettype,
2959 &tupdesc);
2960
2963 {
2964 /* Composite data type, e.g. a table's row type */
2965 Assert(tupdesc);
2966 expandTupleDesc(tupdesc, rte->eref,
2967 rtfunc->funccolcount, atts_done,
2968 rtindex, sublevels_up,
2969 returning_type, location,
2970 include_dropped, colnames, colvars);
2971 }
2972 else if (functypclass == TYPEFUNC_SCALAR)
2973 {
2974 /* Base data type, i.e. scalar */
2975 if (colnames)
2976 *colnames = lappend(*colnames,
2977 list_nth(rte->eref->colnames,
2978 atts_done));
2979
2980 if (colvars)
2981 {
2982 Var *varnode;
2983
2984 varnode = makeVar(rtindex, atts_done + 1,
2986 exprTypmod(rtfunc->funcexpr),
2987 exprCollation(rtfunc->funcexpr),
2988 sublevels_up);
2989 varnode->varreturningtype = returning_type;
2990 varnode->location = location;
2991
2993 }
2994 }
2995 else if (functypclass == TYPEFUNC_RECORD)
2996 {
2997 if (colnames)
2998 {
2999 List *namelist;
3000
3001 /* extract appropriate subset of column list */
3002 namelist = list_copy_tail(rte->eref->colnames,
3003 atts_done);
3005 rtfunc->funccolcount);
3006 *colnames = list_concat(*colnames, namelist);
3007 }
3008
3009 if (colvars)
3010 {
3011 ListCell *l1;
3012 ListCell *l2;
3013 ListCell *l3;
3014 int attnum = atts_done;
3015
3016 forthree(l1, rtfunc->funccoltypes,
3017 l2, rtfunc->funccoltypmods,
3018 l3, rtfunc->funccolcollations)
3019 {
3020 Oid attrtype = lfirst_oid(l1);
3021 int32 attrtypmod = lfirst_int(l2);
3023 Var *varnode;
3024
3025 attnum++;
3026 varnode = makeVar(rtindex,
3027 attnum,
3028 attrtype,
3029 attrtypmod,
3031 sublevels_up);
3032 varnode->varreturningtype = returning_type;
3033 varnode->location = location;
3035 }
3036 }
3037 }
3038 else
3039 {
3040 /* addRangeTableEntryForFunction should've caught this */
3041 elog(ERROR, "function in FROM has unsupported return type");
3042 }
3043 atts_done += rtfunc->funccolcount;
3044 }
3045
3046 /* Append the ordinality column if any */
3047 if (rte->funcordinality)
3048 {
3049 if (colnames)
3050 *colnames = lappend(*colnames,
3051 llast(rte->eref->colnames));
3052
3053 if (colvars)
3054 {
3055 Var *varnode = makeVar(rtindex,
3056 atts_done + 1,
3057 INT8OID,
3058 -1,
3059 InvalidOid,
3060 sublevels_up);
3061
3062 varnode->varreturningtype = returning_type;
3064 }
3065 }
3066 }
3067 break;
3068 case RTE_JOIN:
3069 {
3070 /* Join RTE */
3071 ListCell *colname;
3073
3074 Assert(list_length(rte->eref->colnames) == list_length(rte->joinaliasvars));
3075
3076 varattno = 0;
3077 forboth(colname, rte->eref->colnames, aliasvar, rte->joinaliasvars)
3078 {
3079 Node *avar = (Node *) lfirst(aliasvar);
3080
3081 varattno++;
3082
3083 /*
3084 * During ordinary parsing, there will never be any
3085 * deleted columns in the join. While this function is
3086 * also used by the rewriter and planner, they do not
3087 * currently call it on any JOIN RTEs. Therefore, this
3088 * next bit is dead code, but it seems prudent to handle
3089 * the case correctly anyway.
3090 */
3091 if (avar == NULL)
3092 {
3093 if (include_dropped)
3094 {
3095 if (colnames)
3096 *colnames = lappend(*colnames,
3097 makeString(pstrdup("")));
3098 if (colvars)
3099 {
3100 /*
3101 * Can't use join's column type here (it might
3102 * be dropped!); but it doesn't really matter
3103 * what type the Const claims to be.
3104 */
3107 InvalidOid));
3108 }
3109 }
3110 continue;
3111 }
3112
3113 if (colnames)
3114 {
3115 char *label = strVal(lfirst(colname));
3116
3117 *colnames = lappend(*colnames,
3119 }
3120
3121 if (colvars)
3122 {
3123 Var *varnode;
3124
3125 /*
3126 * If the joinaliasvars entry is a simple Var, just
3127 * copy it (with adjustment of varlevelsup and
3128 * location); otherwise it is a JOIN USING column and
3129 * we must generate a join alias Var. This matches
3130 * the results that expansion of "join.*" by
3131 * expandNSItemVars would have produced, if we had
3132 * access to the ParseNamespaceItem for the join.
3133 */
3134 if (IsA(avar, Var))
3135 {
3136 varnode = copyObject((Var *) avar);
3137 varnode->varlevelsup = sublevels_up;
3138 }
3139 else
3140 varnode = makeVar(rtindex, varattno,
3141 exprType(avar),
3144 sublevels_up);
3145 varnode->varreturningtype = returning_type;
3146 varnode->location = location;
3147
3149 }
3150 }
3151 }
3152 break;
3153 case RTE_TABLEFUNC:
3154 case RTE_VALUES:
3155 case RTE_CTE:
3157 case RTE_GRAPH_TABLE:
3158 {
3159 /* Tablefunc, Values, CTE, or ENR RTE */
3160 ListCell *aliasp_item = list_head(rte->eref->colnames);
3161 ListCell *lct;
3162 ListCell *lcm;
3163 ListCell *lcc;
3164
3165 varattno = 0;
3166 forthree(lct, rte->coltypes,
3167 lcm, rte->coltypmods,
3168 lcc, rte->colcollations)
3169 {
3170 Oid coltype = lfirst_oid(lct);
3173
3174 varattno++;
3175
3176 if (colnames)
3177 {
3178 /* Assume there is one alias per output column */
3179 if (OidIsValid(coltype))
3180 {
3181 char *label = strVal(lfirst(aliasp_item));
3182
3183 *colnames = lappend(*colnames,
3185 }
3186 else if (include_dropped)
3187 *colnames = lappend(*colnames,
3188 makeString(pstrdup("")));
3189
3190 aliasp_item = lnext(rte->eref->colnames, aliasp_item);
3191 }
3192
3193 if (colvars)
3194 {
3195 if (OidIsValid(coltype))
3196 {
3197 Var *varnode;
3198
3199 varnode = makeVar(rtindex, varattno,
3200 coltype, coltypmod, colcoll,
3201 sublevels_up);
3202 varnode->varreturningtype = returning_type;
3203 varnode->location = location;
3204
3206 }
3207 else if (include_dropped)
3208 {
3209 /*
3210 * It doesn't really matter what type the Const
3211 * claims to be.
3212 */
3215 InvalidOid));
3216 }
3217 }
3218 }
3219 }
3220 break;
3221 case RTE_RESULT:
3222 case RTE_GROUP:
3223 /* These expose no columns, so nothing to do */
3224 break;
3225 default:
3226 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
3227 }
3228}
List * list_truncate(List *list, int new_size)
Definition list.c:631
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition makefuncs.c:388
static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
@ RTE_RESULT
int16 attnum
#define llast(l)
Definition pg_list.h:198

References Assert, attnum, copyObject, elog, ERROR, expandRelation(), expandTupleDesc(), TargetEntry::expr, exprCollation(), exprType(), exprTypmod(), fb(), forboth, forthree, RangeTblFunction::funcexpr, get_expr_result_type(), InvalidOid, IsA, label, lappend(), lfirst, lfirst_int, lfirst_oid, list_concat(), list_copy_tail(), list_head(), list_length(), list_nth(), list_truncate(), llast, lnext(), makeNullConst(), makeString(), makeVar(), NIL, OidIsValid, pstrdup(), TargetEntry::resno, RTE_CTE, RTE_FUNCTION, RTE_GRAPH_TABLE, RTE_GROUP, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, strVal, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, TYPEFUNC_RECORD, and TYPEFUNC_SCALAR.

Referenced by build_physical_tlist(), expandRecordVariable(), ReplaceVarFromTargetList(), set_relation_column_names(), and transformWholeRowRef().

◆ expandTupleDesc()

static void expandTupleDesc ( TupleDesc  tupdesc,
Alias eref,
int  count,
int  offset,
int  rtindex,
int  sublevels_up,
VarReturningType  returning_type,
int  location,
bool  include_dropped,
List **  colnames,
List **  colvars 
)
static

Definition at line 3260 of file parse_relation.c.

3265{
3267 int varattno;
3268
3269 aliascell = (offset < list_length(eref->colnames)) ?
3270 list_nth_cell(eref->colnames, offset) : NULL;
3271
3273 for (varattno = 0; varattno < count; varattno++)
3274 {
3275 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
3276
3277 if (attr->attisdropped)
3278 {
3279 if (include_dropped)
3280 {
3281 if (colnames)
3282 *colnames = lappend(*colnames, makeString(pstrdup("")));
3283 if (colvars)
3284 {
3285 /*
3286 * can't use atttypid here, but it doesn't really matter
3287 * what type the Const claims to be.
3288 */
3291 }
3292 }
3293 if (aliascell)
3294 aliascell = lnext(eref->colnames, aliascell);
3295 continue;
3296 }
3297
3298 if (colnames)
3299 {
3300 char *label;
3301
3302 if (aliascell)
3303 {
3305 aliascell = lnext(eref->colnames, aliascell);
3306 }
3307 else
3308 {
3309 /* If we run out of aliases, use the underlying name */
3310 label = NameStr(attr->attname);
3311 }
3312 *colnames = lappend(*colnames, makeString(pstrdup(label)));
3313 }
3314
3315 if (colvars)
3316 {
3317 Var *varnode;
3318
3319 varnode = makeVar(rtindex, varattno + offset + 1,
3320 attr->atttypid, attr->atttypmod,
3321 attr->attcollation,
3322 sublevels_up);
3323 varnode->varreturningtype = returning_type;
3324 varnode->location = location;
3325
3327 }
3328 }
3329}
static ListCell * list_nth_cell(const List *list, int n)
Definition pg_list.h:309

References Assert, fb(), InvalidOid, label, lappend(), lfirst, list_length(), list_nth_cell(), lnext(), makeNullConst(), makeString(), makeVar(), NameStr, pstrdup(), strVal, and TupleDescAttr().

Referenced by expandRelation(), and expandRTE().

◆ findNSItemForRTE()

static ParseNamespaceItem * findNSItemForRTE ( ParseState pstate,
RangeTblEntry rte 
)
static

Definition at line 3982 of file parse_relation.c.

3983{
3984 while (pstate != NULL)
3985 {
3986 ListCell *l;
3987
3988 foreach(l, pstate->p_namespace)
3989 {
3991
3992 if (nsitem->p_rte == rte)
3993 return nsitem;
3994 }
3995 pstate = pstate->parentParseState;
3996 }
3997 return NULL;
3998}

References fb(), lfirst, ParseState::p_namespace, and ParseState::parentParseState.

Referenced by rte_visible_if_lateral(), and rte_visible_if_qualified().

◆ get_parse_rowmark()

RowMarkClause * get_parse_rowmark ( Query qry,
Index  rtindex 
)

Definition at line 3682 of file parse_relation.c.

3683{
3684 ListCell *l;
3685
3686 foreach(l, qry->rowMarks)
3687 {
3688 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
3689
3690 if (rc->rti == rtindex)
3691 return rc;
3692 }
3693 return NULL;
3694}
List * rowMarks
Definition parsenodes.h:239

References fb(), lfirst, Query::rowMarks, and RowMarkClause::rti.

Referenced by AcquireRewriteLocks(), applyLockingClause(), and ApplyRetrieveRule().

◆ get_rte_attribute_is_dropped()

bool get_rte_attribute_is_dropped ( RangeTblEntry rte,
AttrNumber  attnum 
)

Definition at line 3512 of file parse_relation.c.

3513{
3514 bool result;
3515
3516 switch (rte->rtekind)
3517 {
3518 case RTE_RELATION:
3519 {
3520 /*
3521 * Plain relation RTE --- get the attribute's catalog entry
3522 */
3523 HeapTuple tp;
3525
3527 ObjectIdGetDatum(rte->relid),
3529 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
3530 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
3531 attnum, rte->relid);
3533 result = att_tup->attisdropped;
3534 ReleaseSysCache(tp);
3535 }
3536 break;
3537 case RTE_SUBQUERY:
3538 case RTE_TABLEFUNC:
3539 case RTE_VALUES:
3540 case RTE_CTE:
3541 case RTE_GROUP:
3542 case RTE_GRAPH_TABLE:
3543
3544 /*
3545 * Subselect, Table Functions, Values, CTE, GROUP RTEs, Property
3546 * graph references never have dropped columns
3547 */
3548 result = false;
3549 break;
3551 {
3552 /* Check dropped-ness by testing for valid coltype */
3553 if (attnum <= 0 ||
3554 attnum > list_length(rte->coltypes))
3555 elog(ERROR, "invalid varattno %d", attnum);
3556 result = !OidIsValid((list_nth_oid(rte->coltypes, attnum - 1)));
3557 }
3558 break;
3559 case RTE_JOIN:
3560 {
3561 /*
3562 * A join RTE would not have dropped columns when constructed,
3563 * but one in a stored rule might contain columns that were
3564 * dropped from the underlying tables, if said columns are
3565 * nowhere explicitly referenced in the rule. This will be
3566 * signaled to us by a null pointer in the joinaliasvars list.
3567 */
3568 Var *aliasvar;
3569
3570 if (attnum <= 0 ||
3571 attnum > list_length(rte->joinaliasvars))
3572 elog(ERROR, "invalid varattno %d", attnum);
3573 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3574
3575 result = (aliasvar == NULL);
3576 }
3577 break;
3578 case RTE_FUNCTION:
3579 {
3580 /* Function RTE */
3581 ListCell *lc;
3582 int atts_done = 0;
3583
3584 /*
3585 * Dropped attributes are only possible with functions that
3586 * return named composite types. In such a case we have to
3587 * look up the result type to see if it currently has this
3588 * column dropped. So first, loop over the funcs until we
3589 * find the one that covers the requested column.
3590 */
3591 foreach(lc, rte->functions)
3592 {
3594
3595 if (attnum > atts_done &&
3597 {
3598 TupleDesc tupdesc;
3599
3600 /* If it has a coldeflist, it returns RECORD */
3601 if (rtfunc->funccolnames != NIL)
3602 return false; /* can't have any dropped columns */
3603
3604 tupdesc = get_expr_result_tupdesc(rtfunc->funcexpr,
3605 true);
3606 if (tupdesc)
3607 {
3608 /* Composite data type, e.g. a table's row type */
3609 CompactAttribute *att;
3610
3611 Assert(tupdesc);
3613 att = TupleDescCompactAttr(tupdesc,
3614 attnum - atts_done - 1);
3615 return att->attisdropped;
3616 }
3617 /* Otherwise, it can't have any dropped columns */
3618 return false;
3619 }
3620 atts_done += rtfunc->funccolcount;
3621 }
3622
3623 /* If we get here, must be looking for the ordinality column */
3624 if (rte->funcordinality && attnum == atts_done + 1)
3625 return false;
3626
3627 /* this probably can't happen ... */
3628 ereport(ERROR,
3630 errmsg("column %d of relation \"%s\" does not exist",
3631 attnum,
3632 rte->eref->aliasname)));
3633 result = false; /* keep compiler quiet */
3634 }
3635 break;
3636 case RTE_RESULT:
3637 /* this probably can't happen ... */
3638 ereport(ERROR,
3640 errmsg("column %d of relation \"%s\" does not exist",
3641 attnum,
3642 rte->eref->aliasname)));
3643 result = false; /* keep compiler quiet */
3644 break;
3645 default:
3646 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
3647 result = false; /* keep compiler quiet */
3648 }
3649
3650 return result;
3651}
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition funcapi.c:553
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
static Oid list_nth_oid(const List *list, int n)
Definition pg_list.h:353
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
bool attisdropped
Definition tupdesc.h:78
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:195

References Assert, CompactAttribute::attisdropped, attnum, elog, ereport, errcode(), errmsg, ERROR, fb(), RangeTblFunction::funcexpr, get_expr_result_tupdesc(), GETSTRUCT(), HeapTupleIsValid, Int16GetDatum(), lfirst, list_length(), list_nth(), list_nth_oid(), NIL, ObjectIdGetDatum(), OidIsValid, ReleaseSysCache(), result, RTE_CTE, RTE_FUNCTION, RTE_GRAPH_TABLE, RTE_GROUP, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, SearchSysCache2(), and TupleDescCompactAttr().

Referenced by AcquireRewriteLocks().

◆ get_rte_attribute_name()

char * get_rte_attribute_name ( RangeTblEntry rte,
AttrNumber  attnum 
)

Definition at line 3474 of file parse_relation.c.

3475{
3477 return "*";
3478
3479 /*
3480 * If there is a user-written column alias, use it.
3481 */
3482 if (rte->alias &&
3483 attnum > 0 && attnum <= list_length(rte->alias->colnames))
3484 return strVal(list_nth(rte->alias->colnames, attnum - 1));
3485
3486 /*
3487 * If the RTE is a relation, go to the system catalogs not the
3488 * eref->colnames list. This is a little slower but it will give the
3489 * right answer if the column has been renamed since the eref list was
3490 * built (which can easily happen for rules).
3491 */
3492 if (rte->rtekind == RTE_RELATION)
3493 return get_attname(rte->relid, attnum, false);
3494
3495 /*
3496 * Otherwise use the column name from eref. There should always be one.
3497 */
3498 if (attnum > 0 && attnum <= list_length(rte->eref->colnames))
3499 return strVal(list_nth(rte->eref->colnames, attnum - 1));
3500
3501 /* else caller gave us a bogus attnum */
3502 elog(ERROR, "invalid attnum %d for rangetable entry %s",
3503 attnum, rte->eref->aliasname);
3504 return NULL; /* keep compiler quiet */
3505}
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1045

References attnum, elog, ERROR, fb(), get_attname(), InvalidAttrNumber, list_length(), list_nth(), RTE_RELATION, and strVal.

Referenced by get_name_for_var_field(), get_variable(), print_expr(), and substitute_grouped_columns_mutator().

◆ get_tle_by_resno()

◆ GetCTEForRTE()

CommonTableExpr * GetCTEForRTE ( ParseState pstate,
RangeTblEntry rte,
int  rtelevelsup 
)

Definition at line 593 of file parse_relation.c.

594{
595 Index levelsup;
596 ListCell *lc;
597
598 Assert(rte->rtekind == RTE_CTE);
599 levelsup = rte->ctelevelsup + rtelevelsup;
600 while (levelsup-- > 0)
601 {
602 pstate = pstate->parentParseState;
603 if (!pstate) /* shouldn't happen */
604 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
605 }
606 foreach(lc, pstate->p_ctenamespace)
607 {
609
610 if (strcmp(cte->ctename, rte->ctename) == 0)
611 return cte;
612 }
613 /* shouldn't happen */
614 elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
615 return NULL; /* keep compiler quiet */
616}
unsigned int Index
Definition c.h:754
List * p_ctenamespace
Definition parse_node.h:225

References Assert, CommonTableExpr::ctename, elog, ERROR, fb(), lfirst, ParseState::p_ctenamespace, ParseState::parentParseState, and RTE_CTE.

Referenced by expandRecordVariable(), and markTargetListOrigin().

◆ GetNSItemByRangeTablePosn()

ParseNamespaceItem * GetNSItemByRangeTablePosn ( ParseState pstate,
int  varno,
int  sublevels_up 
)

Definition at line 517 of file parse_relation.c.

520{
521 ListCell *lc;
522
523 while (sublevels_up-- > 0)
524 {
525 pstate = pstate->parentParseState;
526 Assert(pstate != NULL);
527 }
528 foreach(lc, pstate->p_namespace)
529 {
531
532 if (nsitem->p_rtindex == varno)
533 return nsitem;
534 }
535 elog(ERROR, "nsitem not found (internal error)");
536 return NULL; /* keep compiler quiet */
537}

References Assert, elog, ERROR, fb(), lfirst, ParseState::p_namespace, and ParseState::parentParseState.

Referenced by transformMergeStmt().

◆ GetNSItemByVar()

ParseNamespaceItem * GetNSItemByVar ( ParseState pstate,
Var var 
)

Definition at line 546 of file parse_relation.c.

547{
548 int sublevels_up = var->varlevelsup;
549 ListCell *lc;
550
551 while (sublevels_up-- > 0)
552 {
553 pstate = pstate->parentParseState;
554 Assert(pstate != NULL);
555 }
556 foreach(lc, pstate->p_namespace)
557 {
559
560 if (nsitem->p_rtindex == var->varno &&
561 nsitem->p_returning_type == var->varreturningtype)
562 return nsitem;
563 }
564 elog(ERROR, "nsitem not found (internal error)");
565 return NULL; /* keep compiler quiet */
566}
int varno
Definition primnodes.h:270
Index varlevelsup
Definition primnodes.h:295

References Assert, elog, ERROR, fb(), lfirst, ParseState::p_namespace, ParseState::parentParseState, Var::varlevelsup, Var::varno, and Var::varreturningtype.

Referenced by coerce_record_to_complex(), ExpandRowReference(), and ParseComplexProjection().

◆ GetRTEByRangeTablePosn()

RangeTblEntry * GetRTEByRangeTablePosn ( ParseState pstate,
int  varno,
int  sublevels_up 
)

Definition at line 573 of file parse_relation.c.

576{
577 while (sublevels_up-- > 0)
578 {
579 pstate = pstate->parentParseState;
580 Assert(pstate != NULL);
581 }
582 Assert(varno > 0 && varno <= list_length(pstate->p_rtable));
583 return rt_fetch(varno, pstate->p_rtable);
584}
#define rt_fetch(rangetable_index, rangetable)
Definition parsetree.h:31

References Assert, fb(), list_length(), ParseState::p_rtable, ParseState::parentParseState, and rt_fetch.

Referenced by count_rowexpr_columns(), expandRecordVariable(), markTargetListOrigin(), and unknown_attribute().

◆ getRTEPermissionInfo()

RTEPermissionInfo * getRTEPermissionInfo ( List rteperminfos,
RangeTblEntry rte 
)

Definition at line 4080 of file parse_relation.c.

4081{
4083
4084 if (rte->perminfoindex == 0 ||
4085 rte->perminfoindex > list_length(rteperminfos))
4086 elog(ERROR, "invalid perminfoindex %u in RTE with relid %u",
4087 rte->perminfoindex, rte->relid);
4089 rte->perminfoindex - 1);
4090 if (perminfo->relid != rte->relid)
4091 elog(ERROR, "permission info at index %u (with relid=%u) does not match provided RTE (with relid=%u)",
4092 rte->perminfoindex, perminfo->relid, rte->relid);
4093
4094 return perminfo;
4095}
#define list_nth_node(type, list, n)
Definition pg_list.h:359

References elog, ERROR, fb(), list_length(), and list_nth_node.

Referenced by add_rte_to_flat_rtable(), all_rows_selectable(), build_simple_rel(), ExecCheckPermissions(), expand_inherited_rtentry(), generate_query_for_graph_path(), get_rel_all_updated_cols(), get_row_security_policies(), GetResultRTEPermissionInfo(), markQueryForLocking(), markRTEForSelectPriv(), rewriteTargetView(), subquery_planner(), and transformLockingClause().

◆ isFutureCTE()

static bool isFutureCTE ( ParseState pstate,
const char refname 
)
static

Definition at line 317 of file parse_relation.c.

318{
319 for (; pstate != NULL; pstate = pstate->parentParseState)
320 {
321 ListCell *lc;
322
323 foreach(lc, pstate->p_future_ctes)
324 {
326
327 if (strcmp(cte->ctename, refname) == 0)
328 return true;
329 }
330 }
331 return false;
332}
List * p_future_ctes
Definition parse_node.h:226

References CommonTableExpr::ctename, fb(), lfirst, ParseState::p_future_ctes, and ParseState::parentParseState.

Referenced by parserOpenTable().

◆ isLockedRefname()

bool isLockedRefname ( ParseState pstate,
const char refname 
)

Definition at line 2781 of file parse_relation.c.

2782{
2783 ListCell *l;
2784
2785 /*
2786 * If we are in a subquery specified as locked FOR UPDATE/SHARE from
2787 * parent level, then act as though there's a generic FOR UPDATE here.
2788 */
2789 if (pstate->p_locked_from_parent)
2790 return true;
2791
2792 foreach(l, pstate->p_locking_clause)
2793 {
2795
2796 if (lc->lockedRels == NIL)
2797 {
2798 /* all tables used in query */
2799 return true;
2800 }
2801 else if (refname != NULL)
2802 {
2803 /* just the named tables */
2804 ListCell *l2;
2805
2806 foreach(l2, lc->lockedRels)
2807 {
2808 RangeVar *thisrel = (RangeVar *) lfirst(l2);
2809
2810 if (strcmp(refname, thisrel->relname) == 0)
2811 return true;
2812 }
2813 }
2814 }
2815 return false;
2816}
bool p_locked_from_parent
Definition parse_node.h:236
List * p_locking_clause
Definition parse_node.h:235

References fb(), lfirst, NIL, ParseState::p_locked_from_parent, and ParseState::p_locking_clause.

Referenced by addRangeTableEntry(), and transformRangeSubselect().

◆ markNullableIfNeeded()

void markNullableIfNeeded ( ParseState pstate,
Var var 
)

Definition at line 1078 of file parse_relation.c.

1079{
1080 int rtindex = var->varno;
1081 Bitmapset *relids;
1082
1083 /* Find the appropriate pstate */
1084 for (int lv = 0; lv < var->varlevelsup; lv++)
1085 pstate = pstate->parentParseState;
1086
1087 /* Find currently-relevant join relids for the Var's rel */
1088 if (rtindex > 0 && rtindex <= list_length(pstate->p_nullingrels))
1089 relids = (Bitmapset *) list_nth(pstate->p_nullingrels, rtindex - 1);
1090 else
1091 relids = NULL;
1092
1093 /*
1094 * Merge with any already-declared nulling rels. (Typically there won't
1095 * be any, but let's get it right if there are.)
1096 */
1097 if (relids != NULL)
1098 var->varnullingrels = bms_union(var->varnullingrels, relids);
1099}
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
List * p_nullingrels
Definition parse_node.h:219

References bms_union(), fb(), list_length(), list_nth(), ParseState::p_nullingrels, ParseState::parentParseState, Var::varlevelsup, and Var::varno.

Referenced by buildVarFromNSColumn(), expandNSItemVars(), scanNSItemForColumn(), and transformWholeRowRef().

◆ markRTEForSelectPriv()

static void markRTEForSelectPriv ( ParseState pstate,
int  rtindex,
AttrNumber  col 
)
static

Definition at line 1109 of file parse_relation.c.

1110{
1111 RangeTblEntry *rte = rt_fetch(rtindex, pstate->p_rtable);
1112
1113 if (rte->rtekind == RTE_RELATION)
1114 {
1116
1117 /* Make sure the rel as a whole is marked for SELECT access */
1119 perminfo->requiredPerms |= ACL_SELECT;
1120 /* Must offset the attnum to fit in a bitmapset */
1121 perminfo->selectedCols =
1122 bms_add_member(perminfo->selectedCols,
1124 }
1125 else if (rte->rtekind == RTE_JOIN)
1126 {
1127 if (col == InvalidAttrNumber)
1128 {
1129 /*
1130 * A whole-row reference to a join has to be treated as whole-row
1131 * references to the two inputs.
1132 */
1133 JoinExpr *j;
1134
1135 if (rtindex > 0 && rtindex <= list_length(pstate->p_joinexprs))
1136 j = list_nth_node(JoinExpr, pstate->p_joinexprs, rtindex - 1);
1137 else
1138 j = NULL;
1139 if (j == NULL)
1140 elog(ERROR, "could not find JoinExpr for whole-row reference");
1141
1142 /* Note: we can't see FromExpr here */
1143 if (IsA(j->larg, RangeTblRef))
1144 {
1145 int varno = ((RangeTblRef *) j->larg)->rtindex;
1146
1148 }
1149 else if (IsA(j->larg, JoinExpr))
1150 {
1151 int varno = ((JoinExpr *) j->larg)->rtindex;
1152
1154 }
1155 else
1156 elog(ERROR, "unrecognized node type: %d",
1157 (int) nodeTag(j->larg));
1158 if (IsA(j->rarg, RangeTblRef))
1159 {
1160 int varno = ((RangeTblRef *) j->rarg)->rtindex;
1161
1163 }
1164 else if (IsA(j->rarg, JoinExpr))
1165 {
1166 int varno = ((JoinExpr *) j->rarg)->rtindex;
1167
1169 }
1170 else
1171 elog(ERROR, "unrecognized node type: %d",
1172 (int) nodeTag(j->rarg));
1173 }
1174 else
1175 {
1176 /*
1177 * Join alias Vars for ordinary columns must refer to merged JOIN
1178 * USING columns. We don't need to do anything here, because the
1179 * join input columns will also be referenced in the join's qual
1180 * clause, and will get marked for select privilege there.
1181 */
1182 }
1183 }
1184 /* other RTE types don't require privilege marking */
1185}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
#define nodeTag(nodeptr)
Definition nodes.h:137
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
static void markRTEForSelectPriv(ParseState *pstate, int rtindex, AttrNumber col)
List * p_joinexprs
Definition parse_node.h:218
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27

References ACL_SELECT, bms_add_member(), elog, ERROR, fb(), FirstLowInvalidHeapAttributeNumber, getRTEPermissionInfo(), InvalidAttrNumber, IsA, j, list_length(), list_nth_node, markRTEForSelectPriv(), nodeTag, ParseState::p_joinexprs, ParseState::p_rtable, ParseState::p_rteperminfos, rt_fetch, RTE_JOIN, and RTE_RELATION.

Referenced by markRTEForSelectPriv(), and markVarForSelectPriv().

◆ markVarForSelectPriv()

void markVarForSelectPriv ( ParseState pstate,
Var var 
)

Definition at line 1193 of file parse_relation.c.

1194{
1195 Index lv;
1196
1197 Assert(IsA(var, Var));
1198 /* Find the appropriate pstate if it's an uplevel Var */
1199 for (lv = 0; lv < var->varlevelsup; lv++)
1200 pstate = pstate->parentParseState;
1201 markRTEForSelectPriv(pstate, var->varno, var->varattno);
1202}
AttrNumber varattno
Definition primnodes.h:275

References Assert, fb(), IsA, markRTEForSelectPriv(), ParseState::parentParseState, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by expandNSItemAttrs(), ExpandSingleTable(), scanNSItemForColumn(), transformForPortionOfClause(), transformJoinUsingClause(), and transformWholeRowRef().

◆ parserOpenTable()

Relation parserOpenTable ( ParseState pstate,
const RangeVar relation,
LOCKMODE  lockmode 
)

Definition at line 1459 of file parse_relation.c.

1460{
1461 Relation rel;
1463
1465 rel = table_openrv_extended(relation, lockmode, true);
1466 if (rel == NULL)
1467 {
1468 if (relation->schemaname)
1469 ereport(ERROR,
1471 errmsg("relation \"%s.%s\" does not exist",
1472 relation->schemaname, relation->relname)));
1473 else
1474 {
1475 /*
1476 * An unqualified name might have been meant as a reference to
1477 * some not-yet-in-scope CTE. The bare "does not exist" message
1478 * has proven remarkably unhelpful for figuring out such problems,
1479 * so we take pains to offer a specific hint.
1480 */
1481 if (isFutureCTE(pstate, relation->relname))
1482 ereport(ERROR,
1484 errmsg("relation \"%s\" does not exist",
1485 relation->relname),
1486 errdetail("There is a WITH item named \"%s\", but it cannot be referenced from this part of the query.",
1487 relation->relname),
1488 errhint("Use WITH RECURSIVE, or re-order the WITH items to remove forward references.")));
1489 else
1490 ereport(ERROR,
1492 errmsg("relation \"%s\" does not exist",
1493 relation->relname)));
1494 }
1495 }
1497 return rel;
1498}
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition parse_node.c:156
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition parse_node.c:140
static bool isFutureCTE(ParseState *pstate, const char *refname)
char * schemaname
Definition primnodes.h:81
Relation table_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition table.c:103

References cancel_parser_errposition_callback(), ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errdetail(), errhint(), errmsg, ERROR, fb(), isFutureCTE(), RangeVar::location, RangeVar::relname, RangeVar::schemaname, setup_parser_errposition_callback(), and table_openrv_extended().

Referenced by addRangeTableEntry(), and setTargetTable().

◆ refnameNamespaceItem()

ParseNamespaceItem * refnameNamespaceItem ( ParseState pstate,
const char schemaname,
const char refname,
int  location,
int sublevels_up 
)

Definition at line 130 of file parse_relation.c.

135{
136 Oid relId = InvalidOid;
137
138 if (sublevels_up)
139 *sublevels_up = 0;
140
141 if (schemaname != NULL)
142 {
144
145 /*
146 * We can use LookupNamespaceNoError() here because we are only
147 * interested in finding existing RTEs. Checking USAGE permission on
148 * the schema is unnecessary since it would have already been checked
149 * when the RTE was made. Furthermore, we want to report "RTE not
150 * found", not "no permissions for schema", if the name happens to
151 * match a schema name the user hasn't got access to.
152 */
155 return NULL;
156 relId = get_relname_relid(refname, namespaceId);
157 if (!OidIsValid(relId))
158 return NULL;
159 }
160
161 while (pstate != NULL)
162 {
164
165 if (OidIsValid(relId))
166 result = scanNameSpaceForRelid(pstate, relId, location);
167 else
168 result = scanNameSpaceForRefname(pstate, refname, location);
169
170 if (result)
171 return result;
172
173 if (sublevels_up)
174 (*sublevels_up)++;
175 else
176 break;
177
178 pstate = pstate->parentParseState;
179 }
180 return NULL;
181}
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2191
Oid LookupNamespaceNoError(const char *nspname)
Definition namespace.c:3427
static ParseNamespaceItem * scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location)
static ParseNamespaceItem * scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)

References fb(), get_relname_relid(), InvalidOid, LookupNamespaceNoError(), OidIsValid, ParseState::parentParseState, result, scanNameSpaceForRefname(), and scanNameSpaceForRelid().

Referenced by errorMissingRTE(), ExpandColumnRefStar(), transformColumnRef(), and transformReturningClause().

◆ rte_visible_if_lateral()

static bool rte_visible_if_lateral ( ParseState pstate,
RangeTblEntry rte 
)
static

Definition at line 4010 of file parse_relation.c.

4011{
4013
4014 /* If LATERAL *is* active, we're clearly barking up the wrong tree */
4015 if (pstate->p_lateral_active)
4016 return false;
4017 nsitem = findNSItemForRTE(pstate, rte);
4018 if (nsitem)
4019 {
4020 /* Found it, report whether it's LATERAL-only */
4021 return nsitem->p_lateral_only && nsitem->p_lateral_ok;
4022 }
4023 return false;
4024}
static ParseNamespaceItem * findNSItemForRTE(ParseState *pstate, RangeTblEntry *rte)

References fb(), findNSItemForRTE(), and ParseState::p_lateral_active.

Referenced by errorMissingColumn(), and errorMissingRTE().

◆ rte_visible_if_qualified()

static bool rte_visible_if_qualified ( ParseState pstate,
RangeTblEntry rte 
)
static

Definition at line 4030 of file parse_relation.c.

4031{
4033
4034 if (nsitem)
4035 {
4036 /* Found it, report whether it's relation-only */
4037 return nsitem->p_rel_visible && !nsitem->p_cols_visible;
4038 }
4039 return false;
4040}

References fb(), and findNSItemForRTE().

Referenced by errorMissingColumn().

◆ scanNameSpaceForCTE()

CommonTableExpr * scanNameSpaceForCTE ( ParseState pstate,
const char refname,
Index ctelevelsup 
)

Definition at line 286 of file parse_relation.c.

288{
289 Index levelsup;
290
291 for (levelsup = 0;
292 pstate != NULL;
293 pstate = pstate->parentParseState, levelsup++)
294 {
295 ListCell *lc;
296
297 foreach(lc, pstate->p_ctenamespace)
298 {
300
301 if (strcmp(cte->ctename, refname) == 0)
302 {
303 *ctelevelsup = levelsup;
304 return cte;
305 }
306 }
307 }
308 return NULL;
309}

References CommonTableExpr::ctename, fb(), lfirst, ParseState::p_ctenamespace, and ParseState::parentParseState.

Referenced by getNSItemForSpecialRelationTypes(), and searchRangeTableForRel().

◆ scanNameSpaceForENR()

bool scanNameSpaceForENR ( ParseState pstate,
const char refname 
)

Definition at line 339 of file parse_relation.c.

340{
341 return name_matches_visible_ENR(pstate, refname);
342}
bool name_matches_visible_ENR(ParseState *pstate, const char *refname)
Definition parse_enr.c:20

References name_matches_visible_ENR().

Referenced by getNSItemForSpecialRelationTypes(), searchRangeTableForRel(), and setTargetTable().

◆ scanNameSpaceForRefname()

static ParseNamespaceItem * scanNameSpaceForRefname ( ParseState pstate,
const char refname,
int  location 
)
static

Definition at line 201 of file parse_relation.c.

202{
204 ListCell *l;
205
206 foreach(l, pstate->p_namespace)
207 {
209
210 /* Ignore columns-only items */
211 if (!nsitem->p_rel_visible)
212 continue;
213 /* If not inside LATERAL, ignore lateral-only items */
214 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
215 continue;
216
217 if (strcmp(nsitem->p_names->aliasname, refname) == 0)
218 {
219 if (result)
222 errmsg("table reference \"%s\" is ambiguous",
223 refname),
224 parser_errposition(pstate, location)));
225 check_lateral_ref_ok(pstate, nsitem, location);
226 result = nsitem;
227 }
228 }
229 return result;
230}

References check_lateral_ref_ok(), ereport, errcode(), errmsg, ERROR, fb(), lfirst, ParseState::p_lateral_active, ParseState::p_namespace, parser_errposition(), and result.

Referenced by refnameNamespaceItem().

◆ scanNameSpaceForRelid()

static ParseNamespaceItem * scanNameSpaceForRelid ( ParseState pstate,
Oid  relid,
int  location 
)
static

Definition at line 241 of file parse_relation.c.

242{
244 ListCell *l;
245
246 foreach(l, pstate->p_namespace)
247 {
249 RangeTblEntry *rte = nsitem->p_rte;
250
251 /* Ignore columns-only items */
252 if (!nsitem->p_rel_visible)
253 continue;
254 /* If not inside LATERAL, ignore lateral-only items */
255 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
256 continue;
257 /* Ignore OLD/NEW namespace items that can appear in RETURNING */
258 if (nsitem->p_returning_type != VAR_RETURNING_DEFAULT)
259 continue;
260
261 /* yes, the test for alias == NULL should be there... */
262 if (rte->rtekind == RTE_RELATION &&
263 rte->relid == relid &&
264 rte->alias == NULL)
265 {
266 if (result)
269 errmsg("table reference %u is ambiguous",
270 relid),
271 parser_errposition(pstate, location)));
272 check_lateral_ref_ok(pstate, nsitem, location);
273 result = nsitem;
274 }
275 }
276 return result;
277}

References check_lateral_ref_ok(), ereport, errcode(), errmsg, ERROR, fb(), lfirst, ParseState::p_lateral_active, ParseState::p_namespace, parser_errposition(), result, RTE_RELATION, and VAR_RETURNING_DEFAULT.

Referenced by refnameNamespaceItem().

◆ scanNSItemForColumn()

Node * scanNSItemForColumn ( ParseState pstate,
ParseNamespaceItem nsitem,
int  sublevels_up,
const char colname,
int  location 
)

Definition at line 716 of file parse_relation.c.

718{
719 RangeTblEntry *rte = nsitem->p_rte;
720 int attnum;
721 Var *var;
722
723 /*
724 * Scan the nsitem's column names (or aliases) for a match. Complain if
725 * multiple matches.
726 */
727 attnum = scanRTEForColumn(pstate, rte, nsitem->p_names,
728 colname, location,
729 0, NULL);
730
732 return NULL; /* Return NULL if no match */
733
734 /* In constraint check, no system column is allowed except tableOid */
739 errmsg("system column \"%s\" reference in check constraint is invalid",
740 colname),
741 parser_errposition(pstate, location)));
742
743 /*
744 * In generated column, no system column is allowed except tableOid.
745 * (Required for stored generated, but we also do it for virtual generated
746 * for now for consistency.)
747 */
752 errmsg("cannot use system column \"%s\" in column generation expression",
753 colname),
754 parser_errposition(pstate, location)));
755
756 /*
757 * In a MERGE WHEN condition, no system column is allowed except tableOid
758 */
759 if (pstate->p_expr_kind == EXPR_KIND_MERGE_WHEN &&
763 errmsg("cannot use system column \"%s\" in MERGE WHEN condition",
764 colname),
765 parser_errposition(pstate, location)));
766
767 /* Found a valid match, so build a Var */
769 {
770 /* Get attribute data from the ParseNamespaceColumn array */
771 ParseNamespaceColumn *nscol = &nsitem->p_nscolumns[attnum - 1];
772
773 /* Complain if dropped column. See notes in scanRTEForColumn. */
774 if (nscol->p_varno == 0)
777 errmsg("column \"%s\" of relation \"%s\" does not exist",
778 colname,
779 nsitem->p_names->aliasname)));
780
781 var = makeVar(nscol->p_varno,
782 nscol->p_varattno,
783 nscol->p_vartype,
784 nscol->p_vartypmod,
785 nscol->p_varcollid,
786 sublevels_up);
787 /* makeVar doesn't offer parameters for these, so set them by hand: */
788 var->varnosyn = nscol->p_varnosyn;
789 var->varattnosyn = nscol->p_varattnosyn;
790 }
791 else
792 {
793 /* System column, so use predetermined type data */
795
797 var = makeVar(nsitem->p_rtindex,
798 attnum,
799 sysatt->atttypid,
800 sysatt->atttypmod,
801 sysatt->attcollation,
802 sublevels_up);
803 }
804 var->location = location;
805
806 /* Mark Var for RETURNING OLD/NEW, as necessary */
807 var->varreturningtype = nsitem->p_returning_type;
808
809 /* Mark Var if it's nulled by any outer joins */
810 markNullableIfNeeded(pstate, var);
811
812 /* Require read access to the column */
813 markVarForSelectPriv(pstate, var);
814
815 return (Node *) var;
816}
@ EXPR_KIND_MERGE_WHEN
Definition parse_node.h:58
@ EXPR_KIND_GENERATED_COLUMN
Definition parse_node.h:84
@ EXPR_KIND_CHECK_CONSTRAINT
Definition parse_node.h:69
static int scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, Alias *eref, const char *colname, int location, int fuzzy_rte_penalty, FuzzyAttrMatchState *fuzzystate)
ParseExprKind p_expr_kind
Definition parse_node.h:232
#define TableOidAttributeNumber
Definition sysattr.h:26

References attnum, ereport, errcode(), errmsg, ERROR, EXPR_KIND_CHECK_CONSTRAINT, EXPR_KIND_GENERATED_COLUMN, EXPR_KIND_MERGE_WHEN, fb(), FormData_pg_attribute, InvalidAttrNumber, Var::location, makeVar(), markNullableIfNeeded(), markVarForSelectPriv(), ParseState::p_expr_kind, parser_errposition(), scanRTEForColumn(), SystemAttributeDefinition(), TableOidAttributeNumber, and Var::varreturningtype.

Referenced by colNameToVar(), ParseComplexProjection(), and transformColumnRef().

◆ scanRTEForColumn()

static int scanRTEForColumn ( ParseState pstate,
RangeTblEntry rte,
Alias eref,
const char colname,
int  location,
int  fuzzy_rte_penalty,
FuzzyAttrMatchState fuzzystate 
)
static

Definition at line 843 of file parse_relation.c.

848{
850 int attnum = 0;
851 ListCell *c;
852
853 /*
854 * Scan the user column names (or aliases) for a match. Complain if
855 * multiple matches.
856 *
857 * Note: eref->colnames may include entries for dropped columns, but those
858 * will be empty strings that cannot match any legal SQL identifier, so we
859 * don't bother to test for that case here.
860 *
861 * Should this somehow go wrong and we try to access a dropped column,
862 * we'll still catch it by virtue of the check in scanNSItemForColumn().
863 * Callers interested in finding match with shortest distance need to
864 * defend against this directly, though.
865 */
866 foreach(c, eref->colnames)
867 {
868 const char *attcolname = strVal(lfirst(c));
869
870 attnum++;
871 if (strcmp(attcolname, colname) == 0)
872 {
873 if (result)
876 errmsg("column reference \"%s\" is ambiguous",
877 colname),
878 parser_errposition(pstate, location)));
879 result = attnum;
880 }
881
882 /* Update fuzzy match state, if provided. */
883 if (fuzzystate != NULL)
885 rte, attcolname, colname, attnum);
886 }
887
888 /*
889 * If we have a unique match, return it. Note that this allows a user
890 * alias to override a system column name (such as OID) without error.
891 */
892 if (result)
893 return result;
894
895 /*
896 * If the RTE represents a real relation, consider system column names.
897 * Composites are only used for pseudo-relations like ON CONFLICT's
898 * excluded.
899 */
900 if (rte->rtekind == RTE_RELATION &&
901 rte->relkind != RELKIND_COMPOSITE_TYPE)
902 {
903 /* quick check to see if name could be a system column */
904 attnum = specialAttNum(colname);
906 {
907 /* now check to see if column actually is defined */
909 ObjectIdGetDatum(rte->relid),
911 result = attnum;
912 }
913 }
914
915 return result;
916}
static void updateFuzzyAttrMatchState(int fuzzy_rte_penalty, FuzzyAttrMatchState *fuzzystate, RangeTblEntry *rte, const char *actual, const char *match, int attnum)
char * c
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition syscache.h:102

References attnum, ereport, errcode(), errmsg, ERROR, fb(), Int16GetDatum(), InvalidAttrNumber, lfirst, ObjectIdGetDatum(), parser_errposition(), result, RTE_RELATION, SearchSysCacheExists2, specialAttNum(), strVal, and updateFuzzyAttrMatchState().

Referenced by scanNSItemForColumn(), and searchRangeTableForCol().

◆ searchRangeTableForCol()

static FuzzyAttrMatchState * searchRangeTableForCol ( ParseState pstate,
const char alias,
const char colname,
int  location 
)
static

Definition at line 995 of file parse_relation.c.

997{
998 ParseState *orig_pstate = pstate;
1000
1001 fuzzystate->distance = MAX_FUZZY_DISTANCE + 1;
1002 fuzzystate->rfirst = NULL;
1003 fuzzystate->rsecond = NULL;
1004 fuzzystate->rexact1 = NULL;
1005 fuzzystate->rexact2 = NULL;
1006
1007 while (pstate != NULL)
1008 {
1009 ListCell *l;
1010
1011 foreach(l, pstate->p_rtable)
1012 {
1014 int fuzzy_rte_penalty = 0;
1015 int attnum;
1016
1017 /*
1018 * Typically, it is not useful to look for matches within join
1019 * RTEs; they effectively duplicate other RTEs for our purposes,
1020 * and if a match is chosen from a join RTE, an unhelpful alias is
1021 * displayed in the final diagnostic message.
1022 */
1023 if (rte->rtekind == RTE_JOIN)
1024 continue;
1025
1026 /*
1027 * If the user didn't specify an alias, then matches against one
1028 * RTE are as good as another. But if the user did specify an
1029 * alias, then we want at least a fuzzy - and preferably an exact
1030 * - match for the range table entry.
1031 */
1032 if (alias != NULL)
1035 rte->eref->aliasname,
1036 strlen(rte->eref->aliasname),
1037 1, 1, 1,
1039 true);
1040
1041 /*
1042 * Scan for a matching column, and update fuzzystate. Non-exact
1043 * matches are dealt with inside scanRTEForColumn, but exact
1044 * matches are handled here. (There won't be more than one exact
1045 * match in the same RTE, else we'd have thrown error earlier.)
1046 */
1048 colname, location,
1051 {
1052 if (fuzzystate->rexact1 == NULL)
1053 {
1054 fuzzystate->rexact1 = rte;
1055 fuzzystate->exact1 = attnum;
1056 }
1057 else
1058 {
1059 /* Needn't worry about overwriting previous rexact2 */
1060 fuzzystate->rexact2 = rte;
1061 fuzzystate->exact2 = attnum;
1062 }
1063 }
1064 }
1065
1066 pstate = pstate->parentParseState;
1067 }
1068
1069 return fuzzystate;
1070}
#define MAX_FUZZY_DISTANCE
int varstr_levenshtein_less_equal(const char *source, int slen, const char *target, int tlen, int ins_c, int del_c, int sub_c, int max_d, bool trusted)

References attnum, fb(), InvalidAttrNumber, lfirst, MAX_FUZZY_DISTANCE, ParseState::p_rtable, palloc_object, ParseState::parentParseState, RTE_JOIN, scanRTEForColumn(), and varstr_levenshtein_less_equal().

Referenced by errorMissingColumn().

◆ searchRangeTableForRel()

static RangeTblEntry * searchRangeTableForRel ( ParseState pstate,
RangeVar relation 
)
static

Definition at line 360 of file parse_relation.c.

361{
362 const char *refname = relation->relname;
363 Oid relId = InvalidOid;
364 CommonTableExpr *cte = NULL;
365 bool isenr = false;
366 Index ctelevelsup = 0;
367 Index levelsup;
368
369 /*
370 * If it's an unqualified name, check for possible CTE matches. A CTE
371 * hides any real relation matches. If no CTE, look for a matching
372 * relation.
373 *
374 * NB: It's not critical that RangeVarGetRelid return the correct answer
375 * here in the face of concurrent DDL. If it doesn't, the worst case
376 * scenario is a less-clear error message. Also, the tables involved in
377 * the query are already locked, which reduces the number of cases in
378 * which surprising behavior can occur. So we do the name lookup
379 * unlocked.
380 */
381 if (!relation->schemaname)
382 {
383 cte = scanNameSpaceForCTE(pstate, refname, &ctelevelsup);
384 if (!cte)
385 isenr = scanNameSpaceForENR(pstate, refname);
386 }
387
388 if (!cte && !isenr)
389 relId = RangeVarGetRelid(relation, NoLock, true);
390
391 /* Now look for RTEs matching either the relation/CTE/ENR or the alias */
392 for (levelsup = 0;
393 pstate != NULL;
394 pstate = pstate->parentParseState, levelsup++)
395 {
396 ListCell *l;
397
398 foreach(l, pstate->p_rtable)
399 {
401
402 if (rte->rtekind == RTE_RELATION &&
403 OidIsValid(relId) &&
404 rte->relid == relId)
405 return rte;
406 if (rte->rtekind == RTE_CTE &&
407 cte != NULL &&
408 rte->ctelevelsup + levelsup == ctelevelsup &&
409 strcmp(rte->ctename, refname) == 0)
410 return rte;
411 if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
412 isenr &&
413 strcmp(rte->enrname, refname) == 0)
414 return rte;
415 if (strcmp(rte->eref->aliasname, refname) == 0)
416 return rte;
417 }
418 }
419 return NULL;
420}
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition namespace.h:98
CommonTableExpr * scanNameSpaceForCTE(ParseState *pstate, const char *refname, Index *ctelevelsup)
bool scanNameSpaceForENR(ParseState *pstate, const char *refname)

References fb(), InvalidOid, lfirst, NoLock, OidIsValid, ParseState::p_rtable, ParseState::parentParseState, RangeVarGetRelid, RangeVar::relname, RTE_CTE, RTE_NAMEDTUPLESTORE, RTE_RELATION, scanNameSpaceForCTE(), scanNameSpaceForENR(), and RangeVar::schemaname.

Referenced by errorMissingRTE().

◆ specialAttNum()

static int specialAttNum ( const char attname)
static

Definition at line 3738 of file parse_relation.c.

3739{
3741
3743 if (sysatt != NULL)
3744 return sysatt->attnum;
3745 return InvalidAttrNumber;
3746}
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition heap.c:248

References attname, fb(), FormData_pg_attribute, InvalidAttrNumber, and SystemAttributeByName().

Referenced by attnameAttNum(), and scanRTEForColumn().

◆ updateFuzzyAttrMatchState()

static void updateFuzzyAttrMatchState ( int  fuzzy_rte_penalty,
FuzzyAttrMatchState fuzzystate,
RangeTblEntry rte,
const char actual,
const char match,
int  attnum 
)
static

Definition at line 623 of file parse_relation.c.

626{
627 int columndistance;
628 int matchlen;
629
630 /* Bail before computing the Levenshtein distance if there's no hope. */
631 if (fuzzy_rte_penalty > fuzzystate->distance)
632 return;
633
634 /*
635 * Outright reject dropped columns, which can appear here with apparent
636 * empty actual names, per remarks within scanRTEForColumn().
637 */
638 if (actual[0] == '\0')
639 return;
640
641 /* Use Levenshtein to compute match distance. */
642 matchlen = strlen(match);
645 1, 1, 1,
646 fuzzystate->distance + 1
648 true);
649
650 /*
651 * If more than half the characters are different, don't treat it as a
652 * match, to avoid making ridiculous suggestions.
653 */
654 if (columndistance > matchlen / 2)
655 return;
656
657 /*
658 * From this point on, we can ignore the distinction between the RTE-name
659 * distance and the column-name distance.
660 */
662
663 /*
664 * If the new distance is less than or equal to that of the best match
665 * found so far, update fuzzystate.
666 */
668 {
669 /* Store new lowest observed distance as first/only match */
670 fuzzystate->distance = columndistance;
671 fuzzystate->rfirst = rte;
672 fuzzystate->first = attnum;
673 fuzzystate->rsecond = NULL;
674 }
675 else if (columndistance == fuzzystate->distance)
676 {
677 /* If we already have a match of this distance, update state */
678 if (fuzzystate->rsecond != NULL)
679 {
680 /*
681 * Too many matches at same distance. Clearly, this value of
682 * distance is too low a bar, so drop these entries while keeping
683 * the current distance value, so that only smaller distances will
684 * be considered interesting. Only if we find something of lower
685 * distance will we re-populate rfirst (via the stanza above).
686 */
687 fuzzystate->rfirst = NULL;
688 fuzzystate->rsecond = NULL;
689 }
690 else if (fuzzystate->rfirst != NULL)
691 {
692 /* Record as provisional second match */
693 fuzzystate->rsecond = rte;
694 fuzzystate->second = attnum;
695 }
696 else
697 {
698 /*
699 * Do nothing. When rfirst is NULL, distance is more than what we
700 * want to consider acceptable, so we should ignore this match.
701 */
702 }
703 }
704}

References attnum, fb(), and varstr_levenshtein_less_equal().

Referenced by scanRTEForColumn().