PostgreSQL Source Code  git master
parse_target.h File Reference
Include dependency graph for parse_target.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ListtransformTargetList (ParseState *pstate, List *targetlist, ParseExprKind exprKind)
 
ListtransformExpressionList (ParseState *pstate, List *exprlist, ParseExprKind exprKind, bool allowDefault)
 
void resolveTargetListUnknowns (ParseState *pstate, List *targetlist)
 
void markTargetListOrigins (ParseState *pstate, List *targetlist)
 
TargetEntrytransformTargetEntry (ParseState *pstate, Node *node, Node *expr, ParseExprKind exprKind, char *colname, bool resjunk)
 
ExprtransformAssignedExpr (ParseState *pstate, Expr *expr, ParseExprKind exprKind, const char *colname, int attrno, List *indirection, int location)
 
void updateTargetListEntry (ParseState *pstate, TargetEntry *tle, char *colname, int attrno, List *indirection, int location)
 
ListcheckInsertTargets (ParseState *pstate, List *cols, List **attrnos)
 
TupleDesc expandRecordVariable (ParseState *pstate, Var *var, int levelsup)
 
char * FigureColname (Node *node)
 
char * FigureIndexColname (Node *node)
 

Function Documentation

◆ checkInsertTargets()

List* checkInsertTargets ( ParseState pstate,
List cols,
List **  attrnos 
)

Definition at line 988 of file parse_target.c.

References attnameAttNum(), bms_add_member(), bms_is_member(), ereport, errcode(), errmsg(), ERROR, i, ResTarget::indirection, InvalidAttrNumber, lappend(), lappend_int(), lfirst, ResTarget::location, makeNode, ResTarget::name, name, NameStr, NIL, ParseState::p_target_relation, parser_errposition(), pstrdup(), RelationData::rd_att, RelationGetNumberOfAttributes, RelationGetRelationName, TupleDescAttr, and ResTarget::val.

Referenced by transformInsertStmt().

989 {
990  *attrnos = NIL;
991 
992  if (cols == NIL)
993  {
994  /*
995  * Generate default column list for INSERT.
996  */
997  int numcol = RelationGetNumberOfAttributes(pstate->p_target_relation);
998 
999  int i;
1000 
1001  for (i = 0; i < numcol; i++)
1002  {
1003  ResTarget *col;
1004  Form_pg_attribute attr;
1005 
1006  attr = TupleDescAttr(pstate->p_target_relation->rd_att, i);
1007 
1008  if (attr->attisdropped)
1009  continue;
1010 
1011  col = makeNode(ResTarget);
1012  col->name = pstrdup(NameStr(attr->attname));
1013  col->indirection = NIL;
1014  col->val = NULL;
1015  col->location = -1;
1016  cols = lappend(cols, col);
1017  *attrnos = lappend_int(*attrnos, i + 1);
1018  }
1019  }
1020  else
1021  {
1022  /*
1023  * Do initial validation of user-supplied INSERT column list.
1024  */
1025  Bitmapset *wholecols = NULL;
1026  Bitmapset *partialcols = NULL;
1027  ListCell *tl;
1028 
1029  foreach(tl, cols)
1030  {
1031  ResTarget *col = (ResTarget *) lfirst(tl);
1032  char *name = col->name;
1033  int attrno;
1034 
1035  /* Lookup column name, ereport on failure */
1036  attrno = attnameAttNum(pstate->p_target_relation, name, false);
1037  if (attrno == InvalidAttrNumber)
1038  ereport(ERROR,
1039  (errcode(ERRCODE_UNDEFINED_COLUMN),
1040  errmsg("column \"%s\" of relation \"%s\" does not exist",
1041  name,
1043  parser_errposition(pstate, col->location)));
1044 
1045  /*
1046  * Check for duplicates, but only of whole columns --- we allow
1047  * INSERT INTO foo (col.subcol1, col.subcol2)
1048  */
1049  if (col->indirection == NIL)
1050  {
1051  /* whole column; must not have any other assignment */
1052  if (bms_is_member(attrno, wholecols) ||
1053  bms_is_member(attrno, partialcols))
1054  ereport(ERROR,
1055  (errcode(ERRCODE_DUPLICATE_COLUMN),
1056  errmsg("column \"%s\" specified more than once",
1057  name),
1058  parser_errposition(pstate, col->location)));
1059  wholecols = bms_add_member(wholecols, attrno);
1060  }
1061  else
1062  {
1063  /* partial column; must not have any whole assignment */
1064  if (bms_is_member(attrno, wholecols))
1065  ereport(ERROR,
1066  (errcode(ERRCODE_DUPLICATE_COLUMN),
1067  errmsg("column \"%s\" specified more than once",
1068  name),
1069  parser_errposition(pstate, col->location)));
1070  partialcols = bms_add_member(partialcols, attrno);
1071  }
1072 
1073  *attrnos = lappend_int(*attrnos, attrno);
1074  }
1075  }
1076 
1077  return cols;
1078 }
List * indirection
Definition: parsenodes.h:441
#define NIL
Definition: pg_list.h:65
Node * val
Definition: parsenodes.h:442
char * name
Definition: parsenodes.h:440
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:428
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:608
int location
Definition: parsenodes.h:443
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:456
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define ereport(elevel, rest)
Definition: elog.h:141
List * lappend_int(List *list, int datum)
Definition: list.c:340
List * lappend(List *list, void *datum)
Definition: list.c:322
TupleDesc rd_att
Definition: rel.h:84
#define makeNode(_type_)
Definition: nodes.h:573
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
#define lfirst(lc)
Definition: pg_list.h:190
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
const char * name
Definition: encode.c:521
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:822
Relation p_target_relation
Definition: parse_node.h:187
int i
#define NameStr(name)
Definition: c.h:616
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427

◆ expandRecordVariable()

TupleDesc expandRecordVariable ( ParseState pstate,
Var var,
int  levelsup 
)

Definition at line 1488 of file parse_target.c.

References Alias::aliasname, Assert, attnum, CreateTemplateTupleDesc(), RangeTblEntry::ctelevelsup, CommonTableExpr::ctequery, elog, RangeTblEntry::eref, ERROR, expandRecordVariable(), expandRTE(), TargetEntry::expr, exprCollation(), exprType(), exprTypmod(), forboth, get_expr_result_tupdesc(), get_tle_by_resno(), GetCTEForRTE(), GetCTETargetList, GetRTEByRangeTablePosn(), i, InvalidAttrNumber, IsA, RangeTblEntry::joinaliasvars, label, lfirst, list_length(), list_nth(), Var::location, MemSet, ParseState::p_rtable, ParseState::parentParseState, TargetEntry::resjunk, Query::rtable, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::self_reference, strVal, RangeTblEntry::subquery, Query::targetList, TupleDescInitEntry(), TupleDescInitEntryCollation(), Var::varattno, Var::varlevelsup, Var::varno, and Var::vartype.

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

1489 {
1490  TupleDesc tupleDesc;
1491  int netlevelsup;
1492  RangeTblEntry *rte;
1494  Node *expr;
1495 
1496  /* Check my caller didn't mess up */
1497  Assert(IsA(var, Var));
1498  Assert(var->vartype == RECORDOID);
1499 
1500  netlevelsup = var->varlevelsup + levelsup;
1501  rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
1502  attnum = var->varattno;
1503 
1504  if (attnum == InvalidAttrNumber)
1505  {
1506  /* Whole-row reference to an RTE, so expand the known fields */
1507  List *names,
1508  *vars;
1509  ListCell *lname,
1510  *lvar;
1511  int i;
1512 
1513  expandRTE(rte, var->varno, 0, var->location, false,
1514  &names, &vars);
1515 
1516  tupleDesc = CreateTemplateTupleDesc(list_length(vars));
1517  i = 1;
1518  forboth(lname, names, lvar, vars)
1519  {
1520  char *label = strVal(lfirst(lname));
1521  Node *varnode = (Node *) lfirst(lvar);
1522 
1523  TupleDescInitEntry(tupleDesc, i,
1524  label,
1525  exprType(varnode),
1526  exprTypmod(varnode),
1527  0);
1528  TupleDescInitEntryCollation(tupleDesc, i,
1529  exprCollation(varnode));
1530  i++;
1531  }
1532  Assert(lname == NULL && lvar == NULL); /* lists same length? */
1533 
1534  return tupleDesc;
1535  }
1536 
1537  expr = (Node *) var; /* default if we can't drill down */
1538 
1539  switch (rte->rtekind)
1540  {
1541  case RTE_RELATION:
1542  case RTE_VALUES:
1543  case RTE_NAMEDTUPLESTORE:
1544  case RTE_RESULT:
1545 
1546  /*
1547  * This case should not occur: a column of a table, values list,
1548  * or ENR shouldn't have type RECORD. Fall through and fail (most
1549  * likely) at the bottom.
1550  */
1551  break;
1552  case RTE_SUBQUERY:
1553  {
1554  /* Subselect-in-FROM: examine sub-select's output expr */
1556  attnum);
1557 
1558  if (ste == NULL || ste->resjunk)
1559  elog(ERROR, "subquery %s does not have attribute %d",
1560  rte->eref->aliasname, attnum);
1561  expr = (Node *) ste->expr;
1562  if (IsA(expr, Var))
1563  {
1564  /*
1565  * Recurse into the sub-select to see what its Var refers
1566  * to. We have to build an additional level of ParseState
1567  * to keep in step with varlevelsup in the subselect.
1568  */
1569  ParseState mypstate;
1570 
1571  MemSet(&mypstate, 0, sizeof(mypstate));
1572  mypstate.parentParseState = pstate;
1573  mypstate.p_rtable = rte->subquery->rtable;
1574  /* don't bother filling the rest of the fake pstate */
1575 
1576  return expandRecordVariable(&mypstate, (Var *) expr, 0);
1577  }
1578  /* else fall through to inspect the expression */
1579  }
1580  break;
1581  case RTE_JOIN:
1582  /* Join RTE --- recursively inspect the alias variable */
1583  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
1584  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
1585  Assert(expr != NULL);
1586  /* We intentionally don't strip implicit coercions here */
1587  if (IsA(expr, Var))
1588  return expandRecordVariable(pstate, (Var *) expr, netlevelsup);
1589  /* else fall through to inspect the expression */
1590  break;
1591  case RTE_FUNCTION:
1592 
1593  /*
1594  * We couldn't get here unless a function is declared with one of
1595  * its result columns as RECORD, which is not allowed.
1596  */
1597  break;
1598  case RTE_TABLEFUNC:
1599 
1600  /*
1601  * Table function cannot have columns with RECORD type.
1602  */
1603  break;
1604  case RTE_CTE:
1605  /* CTE reference: examine subquery's output expr */
1606  if (!rte->self_reference)
1607  {
1608  CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
1609  TargetEntry *ste;
1610 
1611  ste = get_tle_by_resno(GetCTETargetList(cte), attnum);
1612  if (ste == NULL || ste->resjunk)
1613  elog(ERROR, "subquery %s does not have attribute %d",
1614  rte->eref->aliasname, attnum);
1615  expr = (Node *) ste->expr;
1616  if (IsA(expr, Var))
1617  {
1618  /*
1619  * Recurse into the CTE to see what its Var refers to. We
1620  * have to build an additional level of ParseState to keep
1621  * in step with varlevelsup in the CTE; furthermore it
1622  * could be an outer CTE.
1623  */
1624  ParseState mypstate;
1625  Index levelsup;
1626 
1627  MemSet(&mypstate, 0, sizeof(mypstate));
1628  /* this loop must work, since GetCTEForRTE did */
1629  for (levelsup = 0;
1630  levelsup < rte->ctelevelsup + netlevelsup;
1631  levelsup++)
1632  pstate = pstate->parentParseState;
1633  mypstate.parentParseState = pstate;
1634  mypstate.p_rtable = ((Query *) cte->ctequery)->rtable;
1635  /* don't bother filling the rest of the fake pstate */
1636 
1637  return expandRecordVariable(&mypstate, (Var *) expr, 0);
1638  }
1639  /* else fall through to inspect the expression */
1640  }
1641  break;
1642  }
1643 
1644  /*
1645  * We now have an expression we can't expand any more, so see if
1646  * get_expr_result_tupdesc() can do anything with it.
1647  */
1648  return get_expr_result_tupdesc(expr, false);
1649 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
List * joinaliasvars
Definition: parsenodes.h:1030
Index varlevelsup
Definition: primnodes.h:177
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
CommonTableExpr * GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
Definition: nodes.h:525
#define strVal(v)
Definition: value.h:54
#define MemSet(start, val, len)
Definition: c.h:962
AttrNumber varattno
Definition: primnodes.h:172
Definition: primnodes.h:167
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1400
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition: funcapi.c:429
static void * list_nth(const List *list, int n)
Definition: pg_list.h:277
Oid vartype
Definition: primnodes.h:174
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:769
int location
Definition: primnodes.h:182
TupleDesc expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
Index varno
Definition: primnodes.h:170
void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, int location, bool include_dropped, List **colnames, List **colvars)
struct ParseState * parentParseState
Definition: parse_node.h:175
bool self_reference
Definition: parsenodes.h:1058
static char * label
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
unsigned int Index
Definition: c.h:476
int16 attnum
Definition: pg_attribute.h:79
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1393
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:169
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:719
Index ctelevelsup
Definition: parsenodes.h:1057
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:974
Query * subquery
Definition: parsenodes.h:1009
#define elog(elevel,...)
Definition: elog.h:228
int i
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
Alias * eref
Definition: parsenodes.h:1092
Definition: regcomp.c:224
Definition: pg_list.h:50
#define GetCTETargetList(cte)
Definition: parsenodes.h:1444
int16 AttrNumber
Definition: attnum.h:21
List * p_rtable
Definition: parse_node.h:177

◆ FigureColname()

char* FigureColname ( Node node)

Definition at line 1662 of file parse_target.c.

References FigureColnameInternal(), and name.

Referenced by transformRangeFunction(), transformTargetEntry(), and transformXmlExpr().

1663 {
1664  char *name = NULL;
1665 
1666  (void) FigureColnameInternal(node, &name);
1667  if (name != NULL)
1668  return name;
1669  /* default result if we can't guess anything */
1670  return "?column?";
1671 }
static int FigureColnameInternal(Node *node, char **name)
const char * name
Definition: encode.c:521

◆ FigureIndexColname()

char* FigureIndexColname ( Node node)

Definition at line 1681 of file parse_target.c.

References FigureColnameInternal(), and name.

Referenced by transformIndexStmt().

1682 {
1683  char *name = NULL;
1684 
1685  (void) FigureColnameInternal(node, &name);
1686  return name;
1687 }
static int FigureColnameInternal(Node *node, char **name)
const char * name
Definition: encode.c:521

◆ markTargetListOrigins()

void markTargetListOrigins ( ParseState pstate,
List targetlist 
)

Definition at line 330 of file parse_target.c.

References TargetEntry::expr, lfirst, and markTargetListOrigin().

Referenced by transformReturningList(), and transformSelectStmt().

331 {
332  ListCell *l;
333 
334  foreach(l, targetlist)
335  {
336  TargetEntry *tle = (TargetEntry *) lfirst(l);
337 
338  markTargetListOrigin(pstate, tle, (Var *) tle->expr, 0);
339  }
340 }
Definition: primnodes.h:167
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
static void markTargetListOrigin(ParseState *pstate, TargetEntry *tle, Var *var, int levelsup)
Definition: parse_target.c:352

◆ resolveTargetListUnknowns()

void resolveTargetListUnknowns ( ParseState pstate,
List targetlist 
)

Definition at line 300 of file parse_target.c.

References COERCE_IMPLICIT_CAST, coerce_type(), COERCION_IMPLICIT, TargetEntry::expr, exprType(), and lfirst.

Referenced by transformReturningList(), and transformSelectStmt().

301 {
302  ListCell *l;
303 
304  foreach(l, targetlist)
305  {
306  TargetEntry *tle = (TargetEntry *) lfirst(l);
307  Oid restype = exprType((Node *) tle->expr);
308 
309  if (restype == UNKNOWNOID)
310  {
311  tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
312  restype, TEXTOID, -1,
315  -1);
316  }
317  }
318 }
Node * coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:156
Definition: nodes.h:525
unsigned int Oid
Definition: postgres_ext.h:31
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41

◆ transformAssignedExpr()

Expr* transformAssignedExpr ( ParseState pstate,
Expr expr,
ParseExprKind  exprKind,
const char *  colname,
int  attrno,
List indirection,
int  location 
)

Definition at line 457 of file parse_target.c.

References Assert, attnumTypeId(), COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, SetToDefault::collation, ereport, errcode(), errhint(), errmsg(), ERROR, EXPR_KIND_NONE, exprLocation(), exprType(), format_type_be(), IsA, linitial, list_head(), make_var(), makeNullConst(), ParseState::p_expr_kind, ParseState::p_is_insert, ParseState::p_target_rangetblentry, ParseState::p_target_relation, parser_errposition(), RelationData::rd_att, transformAssignmentIndirection(), TupleDescAttr, SetToDefault::typeId, and SetToDefault::typeMod.

Referenced by transformInsertRow(), and updateTargetListEntry().

464 {
465  Relation rd = pstate->p_target_relation;
466  Oid type_id; /* type of value provided */
467  Oid attrtype; /* type of target column */
468  int32 attrtypmod;
469  Oid attrcollation; /* collation of target column */
470  ParseExprKind sv_expr_kind;
471 
472  /*
473  * Save and restore identity of expression type we're parsing. We must
474  * set p_expr_kind here because we can parse subscripts without going
475  * through transformExpr().
476  */
477  Assert(exprKind != EXPR_KIND_NONE);
478  sv_expr_kind = pstate->p_expr_kind;
479  pstate->p_expr_kind = exprKind;
480 
481  Assert(rd != NULL);
482  if (attrno <= 0)
483  ereport(ERROR,
484  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
485  errmsg("cannot assign to system column \"%s\"",
486  colname),
487  parser_errposition(pstate, location)));
488  attrtype = attnumTypeId(rd, attrno);
489  attrtypmod = TupleDescAttr(rd->rd_att, attrno - 1)->atttypmod;
490  attrcollation = TupleDescAttr(rd->rd_att, attrno - 1)->attcollation;
491 
492  /*
493  * If the expression is a DEFAULT placeholder, insert the attribute's
494  * type/typmod/collation into it so that exprType etc will report the
495  * right things. (We expect that the eventually substituted default
496  * expression will in fact have this type and typmod. The collation
497  * likely doesn't matter, but let's set it correctly anyway.) Also,
498  * reject trying to update a subfield or array element with DEFAULT, since
499  * there can't be any default for portions of a column.
500  */
501  if (expr && IsA(expr, SetToDefault))
502  {
503  SetToDefault *def = (SetToDefault *) expr;
504 
505  def->typeId = attrtype;
506  def->typeMod = attrtypmod;
507  def->collation = attrcollation;
508  if (indirection)
509  {
510  if (IsA(linitial(indirection), A_Indices))
511  ereport(ERROR,
512  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
513  errmsg("cannot set an array element to DEFAULT"),
514  parser_errposition(pstate, location)));
515  else
516  ereport(ERROR,
517  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
518  errmsg("cannot set a subfield to DEFAULT"),
519  parser_errposition(pstate, location)));
520  }
521  }
522 
523  /* Now we can use exprType() safely. */
524  type_id = exprType((Node *) expr);
525 
526  /*
527  * If there is indirection on the target column, prepare an array or
528  * subfield assignment expression. This will generate a new column value
529  * that the source value has been inserted into, which can then be placed
530  * in the new tuple constructed by INSERT or UPDATE.
531  */
532  if (indirection)
533  {
534  Node *colVar;
535 
536  if (pstate->p_is_insert)
537  {
538  /*
539  * The command is INSERT INTO table (col.something) ... so there
540  * is not really a source value to work with. Insert a NULL
541  * constant as the source value.
542  */
543  colVar = (Node *) makeNullConst(attrtype, attrtypmod,
544  attrcollation);
545  }
546  else
547  {
548  /*
549  * Build a Var for the column to be updated.
550  */
551  colVar = (Node *) make_var(pstate,
552  pstate->p_target_rangetblentry,
553  attrno,
554  location);
555  }
556 
557  expr = (Expr *)
559  colVar,
560  colname,
561  false,
562  attrtype,
563  attrtypmod,
564  attrcollation,
565  indirection,
566  list_head(indirection),
567  (Node *) expr,
568  location);
569  }
570  else
571  {
572  /*
573  * For normal non-qualified target column, do type checking and
574  * coercion.
575  */
576  Node *orig_expr = (Node *) expr;
577 
578  expr = (Expr *)
579  coerce_to_target_type(pstate,
580  orig_expr, type_id,
581  attrtype, attrtypmod,
584  -1);
585  if (expr == NULL)
586  ereport(ERROR,
587  (errcode(ERRCODE_DATATYPE_MISMATCH),
588  errmsg("column \"%s\" is of type %s"
589  " but expression is of type %s",
590  colname,
591  format_type_be(attrtype),
592  format_type_be(type_id)),
593  errhint("You will need to rewrite or cast the expression."),
594  parser_errposition(pstate, exprLocation(orig_expr))));
595  }
596 
597  pstate->p_expr_kind = sv_expr_kind;
598 
599  return expr;
600 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
int errhint(const char *fmt,...)
Definition: elog.c:1069
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1191
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static Node * transformAssignmentIndirection(ParseState *pstate, Node *basenode, const char *targetName, bool targetIsSubscripting, Oid targetTypeId, int32 targetTypMod, Oid targetCollation, List *indirection, ListCell *indirection_cell, Node *rhs, int location)
Definition: parse_target.c:680
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
unsigned int Oid
Definition: postgres_ext.h:31
ParseExprKind
Definition: parse_node.h:33
signed int int32
Definition: c.h:347
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:335
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
int32 typeMod
Definition: primnodes.h:1282
Oid attnumTypeId(Relation rd, int attid)
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
#define ereport(elevel, rest)
Definition: elog.h:141
RangeTblEntry * p_target_rangetblentry
Definition: parse_node.h:188
ParseExprKind p_expr_kind
Definition: parse_node.h:191
TupleDesc rd_att
Definition: rel.h:84
Var * make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location)
Definition: parse_node.c:188
#define Assert(condition)
Definition: c.h:739
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:822
Relation p_target_relation
Definition: parse_node.h:187
bool p_is_insert
Definition: parse_node.h:189

◆ transformExpressionList()

List* transformExpressionList ( ParseState pstate,
List exprlist,
ParseExprKind  exprKind,
bool  allowDefault 
)

Definition at line 229 of file parse_target.c.

References Assert, ExpandColumnRefStar(), ExpandIndirectionStar(), ColumnRef::fields, A_Indirection::indirection, IsA, lappend(), lfirst, list_concat(), llast, NIL, ParseState::p_multiassign_exprs, and transformExpr().

Referenced by transformInsertStmt(), transformRowExpr(), and transformValuesClause().

231 {
232  List *result = NIL;
233  ListCell *lc;
234 
235  foreach(lc, exprlist)
236  {
237  Node *e = (Node *) lfirst(lc);
238 
239  /*
240  * Check for "something.*". Depending on the complexity of the
241  * "something", the star could appear as the last field in ColumnRef,
242  * or as the last indirection item in A_Indirection.
243  */
244  if (IsA(e, ColumnRef))
245  {
246  ColumnRef *cref = (ColumnRef *) e;
247 
248  if (IsA(llast(cref->fields), A_Star))
249  {
250  /* It is something.*, expand into multiple items */
251  result = list_concat(result,
252  ExpandColumnRefStar(pstate, cref,
253  false));
254  continue;
255  }
256  }
257  else if (IsA(e, A_Indirection))
258  {
260 
261  if (IsA(llast(ind->indirection), A_Star))
262  {
263  /* It is something.*, expand into multiple items */
264  result = list_concat(result,
265  ExpandIndirectionStar(pstate, ind,
266  false, exprKind));
267  continue;
268  }
269  }
270 
271  /*
272  * Not "something.*", so transform as a single expression. If it's a
273  * SetToDefault node and we should allow that, pass it through
274  * unmodified. (transformExpr will throw the appropriate error if
275  * we're disallowing it.)
276  */
277  if (allowDefault && IsA(e, SetToDefault))
278  /* do nothing */ ;
279  else
280  e = transformExpr(pstate, e, exprKind);
281 
282  result = lappend(result, e);
283  }
284 
285  /* Shouldn't have any multiassign items here */
286  Assert(pstate->p_multiassign_exprs == NIL);
287 
288  return result;
289 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:144
#define llast(l)
Definition: pg_list.h:215
Definition: nodes.h:525
List * list_concat(List *list1, const List *list2)
Definition: list.c:516
List * p_multiassign_exprs
Definition: parse_node.h:193
static List * ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, bool make_target_entry)
struct A_Star A_Star
static List * ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind, bool make_target_entry, ParseExprKind exprKind)
List * lappend(List *list, void *datum)
Definition: list.c:322
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
List * indirection
Definition: parsenodes.h:406
e
Definition: preproc-init.c:82
Definition: pg_list.h:50
List * fields
Definition: parsenodes.h:235

◆ transformTargetEntry()

TargetEntry* transformTargetEntry ( ParseState pstate,
Node node,
Node expr,
ParseExprKind  exprKind,
char *  colname,
bool  resjunk 
)

Definition at line 86 of file parse_target.c.

References EXPR_KIND_UPDATE_SOURCE, FigureColname(), IsA, makeTargetEntry(), ParseState::p_next_resno, and transformExpr().

Referenced by findTargetlistEntrySQL99(), and transformTargetList().

92 {
93  /* Transform the node if caller didn't do it already */
94  if (expr == NULL)
95  {
96  /*
97  * If it's a SetToDefault node and we should allow that, pass it
98  * through unmodified. (transformExpr will throw the appropriate
99  * error if we're disallowing it.)
100  */
101  if (exprKind == EXPR_KIND_UPDATE_SOURCE && IsA(node, SetToDefault))
102  expr = node;
103  else
104  expr = transformExpr(pstate, node, exprKind);
105  }
106 
107  if (colname == NULL && !resjunk)
108  {
109  /*
110  * Generate a suitable column name for a column without any explicit
111  * 'AS ColumnName' clause.
112  */
113  colname = FigureColname(node);
114  }
115 
116  return makeTargetEntry((Expr *) expr,
117  (AttrNumber) pstate->p_next_resno++,
118  colname,
119  resjunk);
120 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:144
char * FigureColname(Node *node)
int p_next_resno
Definition: parse_node.h:192
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:236
int16 AttrNumber
Definition: attnum.h:21

◆ transformTargetList()

List* transformTargetList ( ParseState pstate,
List targetlist,
ParseExprKind  exprKind 
)

Definition at line 132 of file parse_target.c.

References Assert, ExpandColumnRefStar(), ExpandIndirectionStar(), EXPR_KIND_UPDATE_SOURCE, ColumnRef::fields, A_Indirection::indirection, IsA, lappend(), lfirst, list_concat(), llast, ResTarget::name, NIL, ParseState::p_multiassign_exprs, transformTargetEntry(), and ResTarget::val.

Referenced by transformReturningList(), transformSelectStmt(), and transformUpdateTargetList().

134 {
135  List *p_target = NIL;
136  bool expand_star;
137  ListCell *o_target;
138 
139  /* Shouldn't have any leftover multiassign items at start */
140  Assert(pstate->p_multiassign_exprs == NIL);
141 
142  /* Expand "something.*" in SELECT and RETURNING, but not UPDATE */
143  expand_star = (exprKind != EXPR_KIND_UPDATE_SOURCE);
144 
145  foreach(o_target, targetlist)
146  {
147  ResTarget *res = (ResTarget *) lfirst(o_target);
148 
149  /*
150  * Check for "something.*". Depending on the complexity of the
151  * "something", the star could appear as the last field in ColumnRef,
152  * or as the last indirection item in A_Indirection.
153  */
154  if (expand_star)
155  {
156  if (IsA(res->val, ColumnRef))
157  {
158  ColumnRef *cref = (ColumnRef *) res->val;
159 
160  if (IsA(llast(cref->fields), A_Star))
161  {
162  /* It is something.*, expand into multiple items */
163  p_target = list_concat(p_target,
164  ExpandColumnRefStar(pstate,
165  cref,
166  true));
167  continue;
168  }
169  }
170  else if (IsA(res->val, A_Indirection))
171  {
172  A_Indirection *ind = (A_Indirection *) res->val;
173 
174  if (IsA(llast(ind->indirection), A_Star))
175  {
176  /* It is something.*, expand into multiple items */
177  p_target = list_concat(p_target,
178  ExpandIndirectionStar(pstate,
179  ind,
180  true,
181  exprKind));
182  continue;
183  }
184  }
185  }
186 
187  /*
188  * Not "something.*", or we want to treat that as a plain whole-row
189  * variable, so transform as a single expression
190  */
191  p_target = lappend(p_target,
192  transformTargetEntry(pstate,
193  res->val,
194  NULL,
195  exprKind,
196  res->name,
197  false));
198  }
199 
200  /*
201  * If any multiassign resjunk items were created, attach them to the end
202  * of the targetlist. This should only happen in an UPDATE tlist. We
203  * don't need to worry about numbering of these items; transformUpdateStmt
204  * will set their resnos.
205  */
206  if (pstate->p_multiassign_exprs)
207  {
208  Assert(exprKind == EXPR_KIND_UPDATE_SOURCE);
209  p_target = list_concat(p_target, pstate->p_multiassign_exprs);
210  pstate->p_multiassign_exprs = NIL;
211  }
212 
213  return p_target;
214 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Node * val
Definition: parsenodes.h:442
char * name
Definition: parsenodes.h:440
#define llast(l)
Definition: pg_list.h:215
List * list_concat(List *list1, const List *list2)
Definition: list.c:516
List * p_multiassign_exprs
Definition: parse_node.h:193
static List * ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, bool make_target_entry)
struct A_Star A_Star
static List * ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind, bool make_target_entry, ParseExprKind exprKind)
List * lappend(List *list, void *datum)
Definition: list.c:322
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
List * indirection
Definition: parsenodes.h:406
TargetEntry * transformTargetEntry(ParseState *pstate, Node *node, Node *expr, ParseExprKind exprKind, char *colname, bool resjunk)
Definition: parse_target.c:86
Definition: pg_list.h:50
List * fields
Definition: parsenodes.h:235

◆ updateTargetListEntry()

void updateTargetListEntry ( ParseState pstate,
TargetEntry tle,
char *  colname,
int  attrno,
List indirection,
int  location 
)

Definition at line 620 of file parse_target.c.

References TargetEntry::expr, EXPR_KIND_UPDATE_TARGET, TargetEntry::resname, TargetEntry::resno, and transformAssignedExpr().

Referenced by transformUpdateTargetList().

626 {
627  /* Fix up expression as needed */
628  tle->expr = transformAssignedExpr(pstate,
629  tle->expr,
631  colname,
632  attrno,
633  indirection,
634  location);
635 
636  /*
637  * Set the resno to identify the target column --- the rewriter and
638  * planner depend on this. We also set the resname to identify the target
639  * column, but this is only for debugging purposes; it should not be
640  * relied on. (In particular, it might be out of date in a stored rule.)
641  */
642  tle->resno = (AttrNumber) attrno;
643  tle->resname = colname;
644 }
Expr * transformAssignedExpr(ParseState *pstate, Expr *expr, ParseExprKind exprKind, const char *colname, int attrno, List *indirection, int location)
Definition: parse_target.c:457
char * resname
Definition: primnodes.h:1395
AttrNumber resno
Definition: primnodes.h:1394
Expr * expr
Definition: primnodes.h:1393
int16 AttrNumber
Definition: attnum.h:21