PostgreSQL Source Code: src/backend/rewrite/rewriteHandler.c File Reference (original) (raw)

Go to the source code of this file.

Data Structures
struct rewrite_event
struct acquireLocksOnSubLinks_context
struct fireRIRonSubLink_context
Typedefs
typedef struct rewrite_event rewrite_event
typedef struct acquireLocksOnSubLinks_context acquireLocksOnSubLinks_context
typedef struct fireRIRonSubLink_context fireRIRonSubLink_context
Functions
static bool acquireLocksOnSubLinks (Node *node, acquireLocksOnSubLinks_context *context)
static Query * rewriteRuleAction (Query *parsetree, Query *rule_action, Node *rule_qual, int rt_index, CmdType event, bool *returning_flag)
static List * adjustJoinTreeList (Query *parsetree, bool removert, int rt_index)
static List * rewriteTargetListIU (List *targetList, CmdType commandType, OverridingKind override, Relation target_relation, RangeTblEntry *values_rte, int values_rte_index, Bitmapset **unused_values_attrnos)
static TargetEntry * process_matched_tle (TargetEntry *src_tle, TargetEntry *prior_tle, const char *attrName)
static Node * get_assignment_input (Node *node)
static Bitmapset * findDefaultOnlyColumns (RangeTblEntry *rte)
static bool rewriteValuesRTE (Query *parsetree, RangeTblEntry *rte, int rti, Relation target_relation, Bitmapset *unused_cols)
static void rewriteValuesRTEToNulls (Query *parsetree, RangeTblEntry *rte)
static void markQueryForLocking (Query *qry, Node *jtnode, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
static List * matchLocks (CmdType event, Relation relation, int varno, Query *parsetree, bool *hasUpdate)
static Query * fireRIRrules (Query *parsetree, List *activeRIRs)
static Bitmapset * adjust_view_column_set (Bitmapset *cols, List *targetlist)
static Node * expand_generated_columns_internal (Node *node, Relation rel, int rt_index, RangeTblEntry *rte, int result_relation)
void AcquireRewriteLocks (Query *parsetree, bool forExecute, bool forUpdatePushedDown)
Node * build_column_default (Relation rel, int attrno)
static bool searchForDefault (RangeTblEntry *rte)
static Query * ApplyRetrieveRule (Query *parsetree, RewriteRule *rule, int rt_index, Relation relation, List *activeRIRs)
static bool fireRIRonSubLink (Node *node, fireRIRonSubLink_context *context)
static Query * CopyAndAddInvertedQual (Query *parsetree, Node *rule_qual, int rt_index, CmdType event)
static List * fireRules (Query *parsetree, int rt_index, CmdType event, List *locks, bool *instead_flag, bool *returning_flag, Query **qual_product)
Query * get_view_query (Relation view)
bool view_has_instead_trigger (Relation view, CmdType event, List *mergeActionList)
static const char * view_col_is_auto_updatable (RangeTblRef *rtr, TargetEntry *tle)
const char * view_query_is_auto_updatable (Query *viewquery, bool check_cols)
static const char * view_cols_are_auto_updatable (Query *viewquery, Bitmapset *required_cols, Bitmapset **updatable_cols, char **non_updatable_col)
int relation_is_updatable (Oid reloid, List *outer_reloids, bool include_triggers, Bitmapset *include_cols)
void error_view_not_updatable (Relation view, CmdType command, List *mergeActionList, const char *detail)
static Query * rewriteTargetView (Query *parsetree, Relation view)
static List * RewriteQuery (Query *parsetree, List *rewrite_events, int orig_rt_length)
Node * expand_generated_columns_in_expr (Node *node, Relation rel, int rt_index)
Node * build_generation_expression (Relation rel, int attrno)
List * QueryRewrite (Query *parsetree)

ALL_EVENTS

rewrite_event

Definition at line 310 of file rewriteHandler.c.

311{

312 if (node == NULL)

313 return false;

315 {

317

318

321 false);

322

323 }

324

325

326

327

328

330}

#define expression_tree_walker(n, w, c)

#define IsA(nodeptr, _type_)

void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)

static bool acquireLocksOnSubLinks(Node *node, acquireLocksOnSubLinks_context *context)

References acquireLocksOnSubLinks(), AcquireRewriteLocks(), expression_tree_walker, acquireLocksOnSubLinks_context::for_execute, IsA, and SubLink::subselect.

Referenced by acquireLocksOnSubLinks(), AcquireRewriteLocks(), CopyAndAddInvertedQual(), fireRIRrules(), rewriteRuleAction(), and rewriteTargetView().

AcquireRewriteLocks()

void AcquireRewriteLocks ( Query * parsetree,
bool forExecute,
bool forUpdatePushedDown
)

Definition at line 148 of file rewriteHandler.c.

151{

153 int rt_index;

155

157

158

159

160

161 rt_index = 0;

162 foreach(l, parsetree->rtable)

163 {

167 List *newaliasvars;

168 Index curinputvarno;

171

172 ++rt_index;

174 {

176

177

178

179

180

181

182

183

184

185

186 if (!forExecute)

188 else if (forUpdatePushedDown)

189 {

190

193 lockmode = rte->rellockmode;

194 }

195 else

196 lockmode = rte->rellockmode;

197

198 rel = table_open(rte->relid, lockmode);

199

200

201

202

203

204 rte->relkind = rel->rd_rel->relkind;

205

207 break;

208

210

211

212

213

214

215

216

217

218

219

220 newaliasvars = NIL;

221 curinputvarno = 0;

222 curinputrte = NULL;

223 foreach(ll, rte->joinaliasvars)

224 {

226 Var *aliasvar = aliasitem;

227

228

230

231

232

233

234

235

236

237

238 if (aliasvar && IsA(aliasvar, Var))

239 {

240

241

242

243

244

245

246

247

248

250 if (aliasvar->varno != curinputvarno)

251 {

252 curinputvarno = aliasvar->varno;

253 if (curinputvarno >= rt_index)

254 elog(ERROR, "unexpected varno %d in JOIN RTE %d",

255 curinputvarno, rt_index);

256 curinputrte = rt_fetch(curinputvarno,

258 }

261 {

262

263 aliasitem = NULL;

264 }

265 }

266 newaliasvars = lappend(newaliasvars, aliasitem);

267 }

268 rte->joinaliasvars = newaliasvars;

269 break;

270

272

273

274

275

276

278 forExecute,

279 (forUpdatePushedDown ||

281 break;

282

283 default:

284

285 break;

286 }

287 }

288

289

290 foreach(l, parsetree->cteList)

291 {

293

295 }

296

297

298

299

300

301 if (parsetree->hasSubLinks)

304}

Assert(PointerIsAligned(start, uint64))

List * lappend(List *list, void *datum)

Node * strip_implicit_coercions(Node *node)

#define query_tree_walker(q, w, c, f)

#define QTW_IGNORE_RC_SUBQUERIES

RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)

bool get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)

#define rt_fetch(rangetable_index, rangetable)

void table_close(Relation relation, LOCKMODE lockmode)

Relation table_open(Oid relationId, LOCKMODE lockmode)

References AccessShareLock, acquireLocksOnSubLinks(), AcquireRewriteLocks(), Assert(), Query::cteList, CommonTableExpr::ctequery, elog, ERROR, acquireLocksOnSubLinks_context::for_execute, get_parse_rowmark(), get_rte_attribute_is_dropped(), IsA, lappend(), lfirst, NIL, NoLock, QTW_IGNORE_RC_SUBQUERIES, query_tree_walker, RelationData::rd_rel, RowShareLock, rt_fetch, Query::rtable, RTE_JOIN, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, strip_implicit_coercions(), RangeTblEntry::subquery, table_close(), table_open(), Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by acquireLocksOnSubLinks(), AcquireRewriteLocks(), ApplyRetrieveRule(), fmgr_sql_validator(), get_query_def(), inline_set_returning_function(), make_ruledef(), prepare_next_query(), print_function_sqlbody(), refresh_matview_datafill(), RevalidateCachedQuery(), and rewriteRuleAction().

adjust_view_column_set()

Definition at line 3044 of file rewriteHandler.c.

3045{

3047 int col;

3048

3049 col = -1;

3051 {

3052

3054

3056 {

3057

3058

3059

3060

3061

3062

3063

3065

3066 foreach(lc, targetlist)

3067 {

3069 Var *var;

3070

3071 if (tle->resjunk)

3072 continue;

3076 }

3077 }

3078 else

3079 {

3080

3081

3082

3083

3084

3086

3087 if (tle != NULL && !tle->resjunk && IsA(tle->expr, Var))

3088 {

3090

3093 }

3094 else

3095 elog(ERROR, "attribute number %d not found in view targetlist",

3096 attno);

3097 }

3098 }

3099

3100 return result;

3101}

#define InvalidAttrNumber

int bms_next_member(const Bitmapset *a, int prevbit)

Bitmapset * bms_add_member(Bitmapset *a, int x)

#define castNode(_type_, nodeptr)

TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)

#define lfirst_node(type, lc)

#define FirstLowInvalidHeapAttributeNumber

References bms_add_member(), bms_next_member(), castNode, elog, ERROR, TargetEntry::expr, FirstLowInvalidHeapAttributeNumber, get_tle_by_resno(), InvalidAttrNumber, IsA, lfirst_node, and Var::varattno.

Referenced by relation_is_updatable(), and rewriteTargetView().

adjustJoinTreeList()

static List * adjustJoinTreeList ( Query * parsetree, bool removert, int rt_index ) static

ApplyRetrieveRule()

Definition at line 1710 of file rewriteHandler.c.

1715{

1716 Query *rule_action;

1719 int numCols;

1720

1722 elog(ERROR, "expected just one rule action");

1723 if (rule->qual != NULL)

1724 elog(ERROR, "cannot handle qualified ON SELECT rule");

1725

1726

1730 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

1731 errmsg("access to non-system view \"%s\" is restricted",

1733

1734 if (rt_index == parsetree->resultRelation)

1735 {

1736

1737

1738

1739

1740

1741

1742

1743

1744

1745

1746

1747

1748

1749

1750

1751

1752

1754 return parsetree;

1758 {

1760 Var *var;

1762

1767

1768

1769

1770

1771

1772

1773

1774

1775

1776

1777

1780 parsetree->resultRelation, 0);

1781

1782

1783

1784

1785

1786

1787

1792 true);

1793

1795

1796

1797 }

1798 else

1799 elog(ERROR, "unrecognized commandType: %d",

1801 }

1802

1803

1804

1805

1806

1807

1808

1809

1811

1812

1813

1814

1815

1816

1818

1820

1821

1822

1823

1824

1825

1826 if (rc != NULL)

1829

1830

1831

1832

1833 rule_action = fireRIRrules(rule_action, activeRIRs);

1834

1835

1836

1837

1838

1839 parsetree->hasRowSecurity |= rule_action->hasRowSecurity;

1840

1841

1842

1843

1844

1846

1848 rte->subquery = rule_action;

1850

1851

1852

1853

1854

1855

1856

1858 rte->inh = false;

1859

1860

1861

1862

1863

1864

1865

1866

1868 while (list_length(rte->eref->colnames) < numCols)

1869 {

1870 rte->eref->colnames = lappend(rte->eref->colnames,

1872 }

1873

1874 return parsetree;

1875}

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

int ExecCleanTargetListLength(List *targetlist)

Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)

TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)

char * pstrdup(const char *in)

static int list_length(const List *l)

int restrict_nonsystem_relation_kind

#define RelationGetRelid(relation)

#define RelationGetRelationName(relation)

#define RelationIsSecurityView(relation)

static void markQueryForLocking(Query *qry, Node *jtnode, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)

static Query * fireRIRrules(Query *parsetree, List *activeRIRs)

void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)

struct TableSampleClause * tablesample

LockClauseStrength strength

LockWaitPolicy waitPolicy

#define RESTRICT_RELKIND_VIEW

#define FirstNormalObjectId

String * makeString(char *str)

References AcquireRewriteLocks(), ChangeVarNodes(), CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_UPDATE, Query::commandType, copyObject, elog, ereport, errcode(), errmsg(), ERROR, ExecCleanTargetListLength(), fireRIRrules(), FirstNormalObjectId, get_parse_rowmark(), RangeTblEntry::inh, Query::jointree, lappend(), linitial, list_length(), makeString(), makeTargetEntry(), makeWholeRowVar(), markQueryForLocking(), pstrdup(), RelationGetRelationName, RelationGetRelid, RelationIsSecurityView, restrict_nonsystem_relation_kind, RESTRICT_RELKIND_VIEW, Query::returningList, rt_fetch, Query::rtable, RTE_SUBQUERY, RangeTblEntry::rtekind, RowMarkClause::strength, RangeTblEntry::subquery, RangeTblEntry::tablesample, Query::targetList, unlikely, and RowMarkClause::waitPolicy.

Referenced by fireRIRrules().

build_column_default()

Definition at line 1227 of file rewriteHandler.c.

1228{

1231 Oid atttype = att_tup->atttypid;

1232 int32 atttypmod = att_tup->atttypmod;

1233 Node *expr = NULL;

1234 Oid exprtype;

1235

1236 if (att_tup->attidentity)

1237 {

1239

1241 nve->typeId = att_tup->atttypid;

1242

1243 return (Node *) nve;

1244 }

1245

1246

1247

1248

1249 if (att_tup->atthasdef)

1250 {

1252 if (expr == NULL)

1253 elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",

1255 }

1256

1257

1258

1259

1260

1261 if (expr == NULL && !att_tup->attgenerated)

1263

1264 if (expr == NULL)

1265 return NULL;

1266

1267

1268

1269

1270

1271

1272

1273

1275

1277 expr, exprtype,

1278 atttype, atttypmod,

1281 -1);

1282 if (expr == NULL)

1284 (errcode(ERRCODE_DATATYPE_MISMATCH),

1285 errmsg("column \"%s\" is of type %s"

1286 " but default expression is of type %s",

1287 NameStr(att_tup->attname),

1290 errhint("You will need to rewrite or cast the expression.")));

1291

1292 return expr;

1293}

int errhint(const char *fmt,...)

char * format_type_be(Oid type_oid)

Node * get_typdefault(Oid typid)

Oid exprType(const Node *expr)

Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)

FormData_pg_attribute * Form_pg_attribute

Oid getIdentitySequence(Relation rel, AttrNumber attnum, bool missing_ok)

Node * TupleDescGetDefault(TupleDesc tupdesc, AttrNumber attnum)

static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)

References COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, elog, ereport, errcode(), errhint(), errmsg(), ERROR, exprType(), format_type_be(), get_typdefault(), getIdentitySequence(), makeNode, NameStr, RelationData::rd_att, RelationGetRelationName, NextValueExpr::seqid, TupleDescAttr(), TupleDescGetDefault(), and NextValueExpr::typeId.

Referenced by ATExecAddColumn(), ATExecAlterColumnType(), ATExecSetExpression(), BeginCopyFrom(), build_generation_expression(), ExecInitGenerated(), rewriteTargetListIU(), rewriteValuesRTE(), and slot_fill_defaults().

build_generation_expression()

Node * build_generation_expression ( Relation rel,
int attrno
)

Definition at line 4499 of file rewriteHandler.c.

4500{

4503 Node *defexpr;

4504 Oid attcollid;

4505

4507 Assert(att_tup->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL);

4508

4510 if (defexpr == NULL)

4511 elog(ERROR, "no generation expression found for column number %d of table \"%s\"",

4513

4514

4515

4516

4517

4518

4519 attcollid = att_tup->attcollation;

4520 if (attcollid && attcollid != exprCollation(defexpr))

4521 {

4523

4524 ce->arg = (Expr *) defexpr;

4525 ce->collOid = attcollid;

4527

4528 defexpr = (Node *) ce;

4529 }

4530

4531 return defexpr;

4532}

Oid exprCollation(const Node *expr)

#define RelationGetDescr(relation)

Node * build_column_default(Relation rel, int attrno)

bool has_generated_virtual

References CollateExpr::arg, Assert(), build_column_default(), CollateExpr::collOid, TupleDescData::constr, elog, ERROR, exprCollation(), TupleConstr::has_generated_virtual, CollateExpr::location, makeNode, RelationGetDescr, RelationGetRelationName, and TupleDescAttr().

Referenced by ExecRelGenVirtualNotNull(), expand_generated_columns_internal(), and expand_virtual_generated_columns().

CopyAndAddInvertedQual()

static Query * CopyAndAddInvertedQual ( Query * parsetree, Node * rule_qual, int rt_index, CmdType event ) static

Definition at line 2319 of file rewriteHandler.c.

2323{

2324

2327

2329

2330

2331

2332

2333

2334

2335

2337

2338

2340

2344 0,

2348 parsetree->resultRelation,

2352 rt_index,

2353 &parsetree->hasSubLinks);

2354

2356

2357 return parsetree;

2358}

void AddInvertedQual(Query *parsetree, Node *qual)

Node * ReplaceVarsFromTargetList(Node *node, int target_varno, int sublevels_up, RangeTblEntry *target_rte, List *targetlist, int result_relation, ReplaceVarsNoMatchOption nomatch_option, int nomatch_varno, bool *outer_hasSubLinks)

@ REPLACEVARS_SUBSTITUTE_NULL

@ REPLACEVARS_CHANGE_VARNO

References acquireLocksOnSubLinks(), AddInvertedQual(), ChangeVarNodes(), CMD_INSERT, CMD_UPDATE, copyObject, acquireLocksOnSubLinks_context::for_execute, PRS2_NEW_VARNO, PRS2_OLD_VARNO, REPLACEVARS_CHANGE_VARNO, REPLACEVARS_SUBSTITUTE_NULL, ReplaceVarsFromTargetList(), rt_fetch, Query::rtable, and Query::targetList.

Referenced by fireRules().

error_view_not_updatable()

void error_view_not_updatable ( Relation view,
CmdType command,
List * mergeActionList,
const char * detail
)

Definition at line 3118 of file rewriteHandler.c.

3122{

3124

3125 switch (command)

3126 {

3129 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

3130 errmsg("cannot insert into view \"%s\"",

3133 errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule."));

3134 break;

3137 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

3138 errmsg("cannot update view \"%s\"",

3141 errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule."));

3142 break;

3145 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

3146 errmsg("cannot delete from view \"%s\"",

3149 errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule."));

3150 break;

3152

3153

3154

3155

3156

3158 {

3159 switch (action->commandType)

3160 {

3164 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

3165 errmsg("cannot insert into view \"%s\"",

3168 errhint("To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger."));

3169 break;

3173 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

3174 errmsg("cannot update view \"%s\"",

3177 errhint("To enable updating the view using MERGE, provide an INSTEAD OF UPDATE trigger."));

3178 break;

3182 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

3183 errmsg("cannot delete from view \"%s\"",

3186 errhint("To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger."));

3187 break;

3189 break;

3190 default:

3191 elog(ERROR, "unrecognized commandType: %d", action->commandType);

3192 break;

3193 }

3194 }

3195 break;

3196 default:

3197 elog(ERROR, "unrecognized CmdType: %d", (int) command);

3198 break;

3199 }

3200}

int errdetail_internal(const char *fmt,...)

#define foreach_node(type, var, lst)

bool trig_update_instead_row

bool trig_delete_instead_row

bool trig_insert_instead_row

References _, generate_unaccent_rules::action, CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_NOTHING, CMD_UPDATE, elog, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, foreach_node, RelationGetRelationName, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, and RelationData::trigdesc.

Referenced by CheckValidResultRel(), RewriteQuery(), and rewriteTargetView().

expand_generated_columns_in_expr()

Node * expand_generated_columns_in_expr ( Node * node,
Relation rel,
int rt_index
)

Definition at line 4473 of file rewriteHandler.c.

4474{

4476

4478 {

4480

4482

4486

4488 }

4489

4490 return node;

4491}

Alias * makeAlias(const char *aliasname, List *colnames)

static Node * expand_generated_columns_internal(Node *node, Relation rel, int rt_index, RangeTblEntry *rte, int result_relation)

References TupleDescData::constr, expand_generated_columns_internal(), TupleConstr::has_generated_virtual, makeAlias(), makeNode, NIL, RelationGetDescr, RelationGetRelationName, RelationGetRelid, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by ATRewriteTable(), ExecRelCheck(), pgoutput_row_filter_init(), QueueCheckConstraintValidation(), TransformPubWhereClauses(), and TriggerEnabled().

expand_generated_columns_internal()

Definition at line 4428 of file rewriteHandler.c.

4430{

4432

4435 {

4437

4438 for (int i = 0; i < tupdesc->natts; i++)

4439 {

4441

4442 if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)

4443 {

4444 Node *defexpr;

4446

4449

4451 tlist = lappend(tlist, te);

4452 }

4453 }

4454

4456

4458 result_relation,

4460 NULL);

4461 }

4462

4463 return node;

4464}

Node * build_generation_expression(Relation rel, int attrno)

References Assert(), build_generation_expression(), ChangeVarNodes(), TupleDescData::constr, TupleConstr::has_generated_virtual, i, lappend(), list_length(), makeTargetEntry(), TupleDescData::natts, NIL, RelationGetDescr, REPLACEVARS_CHANGE_VARNO, ReplaceVarsFromTargetList(), and TupleDescAttr().

Referenced by expand_generated_columns_in_expr().

findDefaultOnlyColumns()

Definition at line 1324 of file rewriteHandler.c.

1325{

1326 Bitmapset *default_only_cols = NULL;

1328

1330 {

1333 int i;

1334

1335 if (default_only_cols == NULL)

1336 {

1337

1338 i = 0;

1339 foreach(lc2, sublist)

1340 {

1342

1343 i++;

1345 default_only_cols = bms_add_member(default_only_cols, i);

1346 }

1347 }

1348 else

1349 {

1350

1351 i = 0;

1352 foreach(lc2, sublist)

1353 {

1355

1356 i++;

1358 default_only_cols = bms_del_member(default_only_cols, i);

1359 }

1360 }

1361

1362

1363

1364

1365

1367 break;

1368 }

1369

1370 return default_only_cols;

1371}

Bitmapset * bms_del_member(Bitmapset *a, int x)

References bms_add_member(), bms_del_member(), bms_is_empty, i, IsA, lfirst, and RangeTblEntry::values_lists.

Referenced by rewriteTargetListIU().

fireRIRrules()

static Query * fireRIRrules ( Query * parsetree, List * activeRIRs ) static

Definition at line 1990 of file rewriteHandler.c.

1991{

1992 int origResultRelation = parsetree->resultRelation;

1993 int rt_index;

1995

1996

1997

1998

1999

2000

2001

2002 foreach(lc, parsetree->cteList)

2003 {

2005

2006 if (cte->search_clause || cte->cycle_clause)

2007 {

2010 }

2011 }

2012

2013

2014

2015

2016

2017 rt_index = 0;

2019 {

2022 List *locks;

2025 int i;

2026

2027 ++rt_index;

2028

2030

2031

2032

2033

2034

2035

2037 {

2039

2040

2041

2042

2043

2044 parsetree->hasRowSecurity |= rte->subquery->hasRowSecurity;

2045

2046 continue;

2047 }

2048

2049

2050

2051

2053 continue;

2054

2055

2056

2057

2058

2059

2060

2061

2062

2063

2064

2065 if (rte->relkind == RELKIND_MATVIEW)

2066 continue;

2067

2068

2069

2070

2071

2072

2073

2074

2077 continue;

2078

2079

2080

2081

2082

2083

2084

2085

2086 if (rt_index != parsetree->resultRelation &&

2088 continue;

2089

2090

2091

2092

2093

2094 if (rt_index == parsetree->resultRelation &&

2095 rt_index != origResultRelation)

2096 continue;

2097

2098

2099

2100

2101

2103

2104

2105

2106

2108 if (rules != NULL)

2109 {

2110 locks = NIL;

2111 for (i = 0; i < rules->numLocks; i++)

2112 {

2115 continue;

2116

2118 }

2119

2120

2121

2122

2123 if (locks != NIL)

2124 {

2126

2129 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),

2130 errmsg("infinite recursion detected in rules for relation \"%s\"",

2133

2134 foreach(l, locks)

2135 {

2137

2140 rt_index,

2141 rel,

2142 activeRIRs);

2143 }

2144

2146 }

2147 }

2148

2150 }

2151

2152

2153 foreach(lc, parsetree->cteList)

2154 {

2156

2159

2160

2161

2162

2163

2164 parsetree->hasRowSecurity |= ((Query *) cte->ctequery)->hasRowSecurity;

2165 }

2166

2167

2168

2169

2170

2171 if (parsetree->hasSubLinks)

2172 {

2174

2177

2180

2181

2182

2183

2184

2185 parsetree->hasRowSecurity |= context.hasRowSecurity;

2186 }

2187

2188

2189

2190

2191

2192

2193

2194 rt_index = 0;

2195 foreach(lc, parsetree->rtable)

2196 {

2199 List *securityQuals;

2200 List *withCheckOptions;

2201 bool hasRowSecurity;

2202 bool hasSubLinks;

2203

2204 ++rt_index;

2205

2206

2208 (rte->relkind != RELKIND_RELATION &&

2209 rte->relkind != RELKIND_PARTITIONED_TABLE))

2210 continue;

2211

2213

2214

2215

2216

2218 &securityQuals, &withCheckOptions,

2219 &hasRowSecurity, &hasSubLinks);

2220

2221 if (securityQuals != NIL || withCheckOptions != NIL)

2222 {

2223 if (hasSubLinks)

2224 {

2227

2228

2229

2230

2231

2234 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),

2235 errmsg("infinite recursion detected in policy for relation \"%s\"",

2237

2239

2240

2241

2242

2243

2244

2245

2246

2247

2251 &context);

2252

2253

2254

2255

2256

2257 fire_context.activeRIRs = activeRIRs;

2259

2262

2265

2266

2267

2268

2269

2270

2271 Assert(hasRowSecurity);

2272

2274 }

2275

2276

2277

2278

2279

2280

2281

2282 rte->securityQuals = list_concat(securityQuals,

2283 rte->securityQuals);

2284

2285 parsetree->withCheckOptions = list_concat(withCheckOptions,

2286 parsetree->withCheckOptions);

2287 }

2288

2289

2290

2291

2292

2293 if (hasRowSecurity)

2294 parsetree->hasRowSecurity = true;

2295 if (hasSubLinks)

2296 parsetree->hasSubLinks = true;

2297

2299 }

2300

2301 return parsetree;

2302}

List * list_concat(List *list1, const List *list2)

List * lappend_oid(List *list, Oid datum)

List * list_delete_last(List *list)

bool list_member_oid(const List *list, Oid datum)

static Query * ApplyRetrieveRule(Query *parsetree, RewriteRule *rule, int rt_index, Relation relation, List *activeRIRs)

bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)

CommonTableExpr * rewriteSearchAndCycle(CommonTableExpr *cte)

void get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index, List **securityQuals, List **withCheckOptions, bool *hasRowSecurity, bool *hasSubLinks)

OnConflictExpr * onConflict

static struct rule * rules

References acquireLocksOnSubLinks(), fireRIRonSubLink_context::activeRIRs, ApplyRetrieveRule(), Assert(), CMD_SELECT, Query::cteList, CommonTableExpr::ctequery, ereport, errcode(), errmsg(), ERROR, OnConflictExpr::exclRelIndex, expression_tree_walker, fireRIRonSubLink(), fireRIRrules(), acquireLocksOnSubLinks_context::for_execute, get_row_security_policies(), fireRIRonSubLink_context::hasRowSecurity, i, lappend(), lappend_oid(), lfirst, lfirst_node, list_concat(), list_delete_last(), list_length(), list_member_oid(), NIL, NoLock, Query::onConflict, QTW_IGNORE_RC_SUBQUERIES, query_tree_walker, rangeTableEntry_used(), RelationData::rd_rules, RelationGetRelationName, RelationGetRelid, rewriteSearchAndCycle(), rt_fetch, Query::rtable, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, rules, RangeTblEntry::subquery, table_close(), and table_open().

Referenced by ApplyRetrieveRule(), fireRIRonSubLink(), fireRIRrules(), and QueryRewrite().

fireRules()

static List * fireRules ( Query * parsetree, int rt_index, CmdType event, List * locks, bool * instead_flag, bool * returning_flag, Query ** qual_product ) static

Definition at line 2390 of file rewriteHandler.c.

2397{

2400

2401 foreach(l, locks)

2402 {

2404 Node *event_qual = rule_lock->qual;

2408

2409

2411 {

2412 if (event_qual != NULL)

2414 else

2415 {

2417 *instead_flag = true;

2418 }

2419 }

2420 else

2422

2424 {

2425

2426

2427

2428

2429

2430

2431

2432

2433

2434

2435

2436

2437 if (!*instead_flag)

2438 {

2439 if (*qual_product == NULL)

2440 *qual_product = copyObject(parsetree);

2442 event_qual,

2443 rt_index,

2444 event);

2445 }

2446 }

2447

2448

2449 foreach(r, actions)

2450 {

2452

2454 continue;

2455

2457 event_qual, rt_index, event,

2458 returning_flag);

2459

2460 rule_action->querySource = qsrc;

2461 rule_action->canSetTag = false;

2462

2463 results = lappend(results, rule_action);

2464 }

2465 }

2466

2467 return results;

2468}

static Query * rewriteRuleAction(Query *parsetree, Query *rule_action, Node *rule_qual, int rt_index, CmdType event, bool *returning_flag)

static Query * CopyAndAddInvertedQual(Query *parsetree, Node *rule_qual, int rt_index, CmdType event)

References RewriteRule::actions, CMD_NOTHING, Query::commandType, CopyAndAddInvertedQual(), copyObject, RewriteRule::isInstead, lappend(), lfirst, NIL, QSRC_INSTEAD_RULE, QSRC_NON_INSTEAD_RULE, QSRC_QUAL_INSTEAD_RULE, RewriteRule::qual, and rewriteRuleAction().

Referenced by RewriteQuery().

get_assignment_input()

static Node * get_assignment_input ( Node * node) static

get_view_query()

Definition at line 2481 of file rewriteHandler.c.

2482{

2483 int i;

2484

2485 Assert(view->rd_rel->relkind == RELKIND_VIEW);

2486

2488 {

2490

2492 {

2493

2495 elog(ERROR, "invalid _RETURN rule action specification");

2496

2498 }

2499 }

2500

2501 elog(ERROR, "failed to find _RETURN rule for view");

2502 return NULL;

2503}

References Assert(), CMD_SELECT, elog, ERROR, i, linitial, list_length(), RuleLock::numLocks, RelationData::rd_rel, RelationData::rd_rules, and RuleLock::rules.

Referenced by ATExecSetRelOptions(), LockViewRecurse(), relation_is_updatable(), and rewriteTargetView().

markQueryForLocking()

Definition at line 1890 of file rewriteHandler.c.

1893{

1894 if (jtnode == NULL)

1895 return;

1897 {

1898 int rti = ((RangeTblRef *) jtnode)->rtindex;

1900

1902 {

1904

1906

1909 }

1911 {

1913

1915 strength, waitPolicy, true);

1916 }

1917

1918 }

1920 {

1923

1926 }

1928 {

1930

1933 }

1934 else

1935 elog(ERROR, "unrecognized node type: %d",

1937}

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

#define ACL_SELECT_FOR_UPDATE

void applyLockingClause(Query *qry, Index rtindex, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)

References ACL_SELECT_FOR_UPDATE, applyLockingClause(), elog, ERROR, FromExpr::fromlist, getRTEPermissionInfo(), IsA, j, Query::jointree, lfirst, markQueryForLocking(), nodeTag, RTEPermissionInfo::requiredPerms, rt_fetch, Query::rtable, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, and RangeTblEntry::subquery.

Referenced by ApplyRetrieveRule(), and markQueryForLocking().

matchLocks()

Definition at line 1635 of file rewriteHandler.c.

1640{

1642 List *matching_locks = NIL;

1643 int nlocks;

1644 int i;

1645

1646 if (rulelocks == NULL)

1647 return NIL;

1648

1650 {

1651 if (parsetree->resultRelation != varno)

1652 return NIL;

1653 }

1654

1655 nlocks = rulelocks->numLocks;

1656

1657 for (i = 0; i < nlocks; i++)

1658 {

1660

1662 *hasUpdate = true;

1663

1664

1665

1666

1667

1668

1669

1671 {

1673 {

1676 continue;

1677 }

1678 else

1679 {

1682 continue;

1683 }

1684

1685

1688 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

1689 errmsg("cannot execute MERGE on relation \"%s\"",

1691 errdetail("MERGE is not supported for relations with rules."));

1692 }

1693

1694 if (oneLock->event == event)

1695 {

1698 matching_locks = lappend(matching_locks, oneLock);

1699 }

1700 }

1701

1702 return matching_locks;

1703}

int errdetail(const char *fmt,...)

#define RULE_FIRES_ON_ORIGIN

#define RULE_FIRES_ON_REPLICA

int SessionReplicationRole

#define SESSION_REPLICATION_ROLE_REPLICA

References CMD_MERGE, CMD_SELECT, CMD_UPDATE, Query::commandType, RewriteRule::enabled, ereport, errcode(), errdetail(), errmsg(), ERROR, RewriteRule::event, i, lappend(), NIL, RuleLock::numLocks, rangeTableEntry_used(), RelationData::rd_rules, RelationGetRelationName, RULE_DISABLED, RULE_FIRES_ON_ORIGIN, RULE_FIRES_ON_REPLICA, RuleLock::rules, SESSION_REPLICATION_ROLE_REPLICA, and SessionReplicationRole.

Referenced by RewriteQuery(), and rewriteValuesRTE().

process_matched_tle()

Definition at line 1045 of file rewriteHandler.c.

1048{

1051 Node *src_expr;

1052 Node *prior_expr;

1053 Node *src_input;

1054 Node *prior_input;

1055 Node *priorbottom;

1056 Node *newexpr;

1057

1058 if (prior_tle == NULL)

1059 {

1060

1061

1062

1063 return src_tle;

1064 }

1065

1066

1067

1068

1069

1070

1071

1072

1073

1074

1075

1076

1077

1078

1079

1080

1081

1082

1083

1084

1085

1086

1087

1088

1089

1090

1091

1092

1093

1094

1095

1096

1097 src_expr = (Node *) src_tle->expr;

1098 prior_expr = (Node *) prior_tle->expr;

1099

1104 {

1105

1109 }

1110

1113 if (src_input == NULL ||

1114 prior_input == NULL ||

1117 (errcode(ERRCODE_SYNTAX_ERROR),

1118 errmsg("multiple assignments to same column \"%s\"",

1119 attrName)));

1120

1121

1122

1123

1124 priorbottom = prior_input;

1125 for (;;)

1126 {

1128

1129 if (newbottom == NULL)

1130 break;

1131 priorbottom = newbottom;

1132 }

1133 if (equal(priorbottom, src_input))

1135 (errcode(ERRCODE_SYNTAX_ERROR),

1136 errmsg("multiple assignments to same column \"%s\"",

1137 attrName)));

1138

1139

1140

1141

1143 {

1145

1147 {

1148

1149 memcpy(fstore, prior_expr, sizeof(FieldStore));

1152 ((FieldStore *) src_expr)->newvals);

1153 fstore->fieldnums =

1155 ((FieldStore *) src_expr)->fieldnums);

1156 }

1157 else

1158 {

1159

1160 memcpy(fstore, src_expr, sizeof(FieldStore));

1161 fstore->arg = (Expr *) prior_expr;

1162 }

1163 newexpr = (Node *) fstore;

1164 }

1166 {

1168

1171 newexpr = (Node *) sbsref;

1172 }

1173 else

1174 {

1176 newexpr = NULL;

1177 }

1178

1179 if (coerce_expr)

1180 {

1181

1183

1184 memcpy(newcoerce, coerce_expr, sizeof(CoerceToDomain));

1185 newcoerce->arg = (Expr *) newexpr;

1186 newexpr = (Node *) newcoerce;

1187 }

1188

1190 result->expr = (Expr *) newexpr;

1191 return result;

1192}

bool equal(const void *a, const void *b)

List * list_concat_copy(const List *list1, const List *list2)

TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)

static Node * get_assignment_input(Node *node)

References arg, FieldStore::arg, CoerceToDomain::arg, elog, equal(), ereport, errcode(), errmsg(), ERROR, TargetEntry::expr, exprType(), flatCopyTargetEntry(), get_assignment_input(), IsA, list_concat_copy(), makeNode, FieldStore::newvals, and SubscriptingRef::refexpr.

Referenced by rewriteTargetListIU().

QueryRewrite()

Definition at line 4545 of file rewriteHandler.c.

4546{

4547 uint64 input_query_id = parsetree->queryId;

4548 List *querylist;

4549 List *results;

4552 bool foundOriginalQuery;

4553 Query *lastInstead;

4554

4555

4556

4557

4559 Assert(parsetree->canSetTag);

4560

4561

4562

4563

4564

4565

4567

4568

4569

4570

4571

4572

4573

4574

4575 results = NIL;

4576 foreach(l, querylist)

4577 {

4579

4581

4582 query->queryId = input_query_id;

4583

4584 results = lappend(results, query);

4585 }

4586

4587

4588

4589

4590

4591

4592

4593

4594

4595

4596

4597

4598

4599

4600

4601

4602

4604 foundOriginalQuery = false;

4605 lastInstead = NULL;

4606

4607 foreach(l, results)

4608 {

4610

4612 {

4613 Assert(query->canSetTag);

4614 Assert(!foundOriginalQuery);

4615 foundOriginalQuery = true;

4616#ifndef USE_ASSERT_CHECKING

4617 break;

4618#endif

4619 }

4620 else

4621 {

4622 Assert(!query->canSetTag);

4623 if (query->commandType == origCmdType &&

4626 lastInstead = query;

4627 }

4628 }

4629

4630 if (!foundOriginalQuery && lastInstead != NULL)

4631 lastInstead->canSetTag = true;

4632

4633 return results;

4634}

static List * RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length)

References Assert(), Query::commandType, fireRIRrules(), lappend(), lfirst, NIL, QSRC_INSTEAD_RULE, QSRC_ORIGINAL, QSRC_QUAL_INSTEAD_RULE, and RewriteQuery().

Referenced by ExecCreateTableAs(), ExplainOneUtility(), ExplainQuery(), PerformCursorOpen(), pg_rewrite_query(), and refresh_matview_datafill().

relation_is_updatable()

int relation_is_updatable ( Oid reloid,
List * outer_reloids,
bool include_triggers,
Bitmapset * include_cols
)

Definition at line 2863 of file rewriteHandler.c.

2867{

2868 int events = 0;

2871

2872#define ALL_EVENTS ((1 << CMD_INSERT) | (1 << CMD_UPDATE) | (1 << CMD_DELETE))

2873

2874

2876

2878

2879

2880

2881

2882

2883

2884

2885 if (rel == NULL)

2886 return 0;

2887

2888

2890 {

2892 return 0;

2893 }

2894

2895

2896 if (rel->rd_rel->relkind == RELKIND_RELATION ||

2897 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)

2898 {

2901 }

2902

2903

2905 if (rulelocks != NULL)

2906 {

2907 int i;

2908

2909 for (i = 0; i < rulelocks->numLocks; i++)

2910 {

2913 {

2915 }

2916 }

2917

2918

2920 {

2922 return events;

2923 }

2924 }

2925

2926

2927 if (include_triggers)

2928 {

2930

2931 if (trigDesc)

2932 {

2939

2940

2942 {

2944 return events;

2945 }

2946 }

2947 }

2948

2949

2950 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)

2951 {

2953

2956 else

2957 {

2958

2965 }

2966

2968 return events;

2969 }

2970

2971

2972 if (rel->rd_rel->relkind == RELKIND_VIEW)

2973 {

2975

2977 {

2979 int auto_events;

2982 Oid baseoid;

2983

2984

2985

2986

2987

2988

2989

2991 &updatable_cols, NULL);

2992

2993 if (include_cols != NULL)

2994 updatable_cols = bms_int_members(updatable_cols, include_cols);

2995

2997 auto_events = (1 << CMD_DELETE);

2998 else

2999 auto_events = ALL_EVENTS;

3000

3001

3002

3003

3004

3005

3006

3010

3011 if (base_rte->relkind != RELKIND_RELATION &&

3012 base_rte->relkind != RELKIND_PARTITIONED_TABLE)

3013 {

3014 baseoid = base_rte->relid;

3015 outer_reloids = lappend_oid(outer_reloids,

3020 outer_reloids,

3021 include_triggers,

3022 include_cols);

3024 }

3025 events |= auto_events;

3026 }

3027 }

3028

3029

3031 return events;

3032}

Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)

FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)

static const char * view_cols_are_auto_updatable(Query *viewquery, Bitmapset *required_cols, Bitmapset **updatable_cols, char **non_updatable_col)

int relation_is_updatable(Oid reloid, List *outer_reloids, bool include_triggers, Bitmapset *include_cols)

Query * get_view_query(Relation view)

static Bitmapset * adjust_view_column_set(Bitmapset *cols, List *targetlist)

const char * view_query_is_auto_updatable(Query *viewquery, bool check_cols)

void relation_close(Relation relation, LOCKMODE lockmode)

Relation try_relation_open(Oid relationId, LOCKMODE lockmode)

void check_stack_depth(void)

ExecForeignInsert_function ExecForeignInsert

ExecForeignUpdate_function ExecForeignUpdate

ExecForeignDelete_function ExecForeignDelete

IsForeignRelUpdatable_function IsForeignRelUpdatable

References AccessShareLock, adjust_view_column_set(), ALL_EVENTS, Assert(), bms_int_members(), bms_is_empty, check_stack_depth(), CMD_DELETE, CMD_INSERT, CMD_UPDATE, RewriteRule::event, FdwRoutine::ExecForeignDelete, FdwRoutine::ExecForeignInsert, FdwRoutine::ExecForeignUpdate, FromExpr::fromlist, get_view_query(), GetFdwRoutineForRelation(), i, FdwRoutine::IsForeignRelUpdatable, RewriteRule::isInstead, Query::jointree, lappend_oid(), linitial, list_delete_last(), list_member_oid(), RuleLock::numLocks, RewriteRule::qual, RelationData::rd_rel, RelationData::rd_rules, relation_close(), relation_is_updatable(), RelationGetRelid, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, RangeTblRef::rtindex, RuleLock::rules, Query::targetList, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, RelationData::trigdesc, try_relation_open(), view_cols_are_auto_updatable(), and view_query_is_auto_updatable().

Referenced by pg_column_is_updatable(), pg_relation_is_updatable(), and relation_is_updatable().

RewriteQuery()

static List * RewriteQuery ( Query * parsetree, List * rewrite_events, int orig_rt_length ) static

Definition at line 3876 of file rewriteHandler.c.

3877{

3879 bool instead = false;

3880 bool returning = false;

3881 bool updatableview = false;

3882 Query *qual_product = NULL;

3885

3886

3887

3888

3889

3890

3891 foreach(lc1, parsetree->cteList)

3892 {

3895 List *newstuff;

3896

3898 continue;

3899

3900 newstuff = RewriteQuery(ctequery, rewrite_events, 0);

3901

3902

3903

3904

3905

3906

3908 {

3909

3916 {

3917

3918

3919

3920

3922 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3923 errmsg("DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH")));

3924 }

3925

3926 Assert(!ctequery->canSetTag);

3927

3929 }

3930 else if (newstuff == NIL)

3931 {

3933 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3934 errmsg("DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH")));

3935 }

3936 else

3937 {

3939

3940

3941 foreach(lc2, newstuff)

3942 {

3944

3947 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3948 errmsg("conditional DO INSTEAD rules are not supported for data-modifying statements in WITH")));

3951 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3952 errmsg("DO ALSO rules are not supported for data-modifying statements in WITH")));

3953 }

3954

3956 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3957 errmsg("multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH")));

3958 }

3959 }

3960

3961

3962

3963

3964

3965

3966

3967

3968

3970 {

3971 int result_relation;

3974 List *locks;

3975 int product_orig_rt_length;

3976 List *product_queries;

3977 bool hasUpdate = false;

3978 int values_rte_index = 0;

3979 bool defaults_remaining = false;

3980

3981 result_relation = parsetree->resultRelation;

3982 Assert(result_relation != 0);

3983 rt_entry = rt_fetch(result_relation, parsetree->rtable);

3985

3986

3987

3988

3989

3991

3992

3993

3994

3996 {

3999

4000

4001

4002

4003

4004

4005

4007 {

4009

4011 {

4014

4016 {

4017

4018 if (values_rte != NULL)

4019 elog(ERROR, "more than one VALUES RTE found");

4020

4021 values_rte = rte;

4022 values_rte_index = rtr->rtindex;

4023 }

4024 }

4025 }

4026

4027 if (values_rte)

4028 {

4029 Bitmapset *unused_values_attrnos = NULL;

4030

4031

4034 parsetree->override,

4035 rt_entry_relation,

4036 values_rte,

4037 values_rte_index,

4038 &unused_values_attrnos);

4039

4040 if (rewriteValuesRTE(parsetree, values_rte, values_rte_index,

4041 rt_entry_relation,

4042 unused_values_attrnos))

4043 defaults_remaining = true;

4044 }

4045 else

4046 {

4047

4051 parsetree->override,

4052 rt_entry_relation,

4053 NULL, 0, NULL);

4054 }

4055

4058 {

4062 parsetree->override,

4063 rt_entry_relation,

4064 NULL, 0, NULL);

4065 }

4066 }

4068 {

4073 parsetree->override,

4074 rt_entry_relation,

4075 NULL, 0, NULL);

4076 }

4078 {

4080

4081

4082

4083

4085 {

4087

4088 switch (action->commandType)

4089 {

4091 case CMD_DELETE:

4092 break;

4095

4096

4097

4098

4099

4100 action->targetList =

4102 action->commandType,

4104 rt_entry_relation,

4105 NULL, 0, NULL);

4106 break;

4107 default:

4108 elog(ERROR, "unrecognized commandType: %d", action->commandType);

4109 break;

4110 }

4111 }

4112 }

4114 {

4115

4116 }

4117 else

4118 elog(ERROR, "unrecognized commandType: %d", (int) event);

4119

4120

4121

4122

4123 locks = matchLocks(event, rt_entry_relation,

4124 result_relation, parsetree, &hasUpdate);

4125

4127 product_queries = fireRules(parsetree,

4128 result_relation,

4129 event,

4130 locks,

4131 &instead,

4132 &returning,

4133 &qual_product);

4134

4135

4136

4137

4138

4139

4140

4141

4142

4143 if (defaults_remaining && product_queries != NIL)

4144 {

4146

4147

4148

4149

4150

4151

4152

4153

4154

4155

4156 foreach(n, product_queries)

4157 {

4160

4164 {

4166

4168 {

4169 int rtindex = ((RangeTblRef *) jtnode)->rtindex;

4171

4177 }

4178 }

4179

4180 values_rte = rt_fetch(values_rte_index, pt->rtable);

4182 elog(ERROR, "failed to find VALUES RTE in product query");

4183

4185 }

4186 }

4187

4188

4189

4190

4191

4192

4193

4194

4195

4196

4197

4198

4199

4200

4201

4202

4203 if (!instead &&

4204 rt_entry_relation->rd_rel->relkind == RELKIND_VIEW &&

4207 {

4208

4209

4210

4211

4212

4213 if (qual_product != NULL)

4217 gettext_noop("Views with conditional DO INSTEAD rules are not automatically updatable."));

4218

4219

4220

4221

4222

4223

4225

4226

4227

4228

4229

4230

4231

4233 product_queries = lcons(parsetree, product_queries);

4234 else

4235 product_queries = lappend(product_queries, parsetree);

4236

4237

4238

4239

4240

4241

4242

4243

4244 instead = true;

4245 returning = true;

4246 updatableview = true;

4247 }

4248

4249

4250

4251

4252

4253 if (product_queries != NIL)

4254 {

4257

4258 foreach(n, rewrite_events)

4259 {

4262 rev->event == event)

4264 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),

4265 errmsg("infinite recursion detected in rules for relation \"%s\"",

4267 }

4268

4271 rev->event = event;

4272 rewrite_events = lappend(rewrite_events, rev);

4273

4274 foreach(n, product_queries)

4275 {

4277 List *newstuff;

4278

4279

4280

4281

4282

4283

4284

4285

4286

4287

4289 pt == parsetree ?

4290 orig_rt_length :

4291 product_orig_rt_length);

4292 rewritten = list_concat(rewritten, newstuff);

4293 }

4294

4296 }

4297

4298

4299

4300

4301

4302

4303

4304

4305 if ((instead || qual_product != NULL) &&

4307 !returning)

4308 {

4309 switch (event)

4310 {

4313 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

4314 errmsg("cannot perform INSERT RETURNING on relation \"%s\"",

4316 errhint("You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause.")));

4317 break;

4320 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

4321 errmsg("cannot perform UPDATE RETURNING on relation \"%s\"",

4323 errhint("You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.")));

4324 break;

4327 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

4328 errmsg("cannot perform DELETE RETURNING on relation \"%s\"",

4330 errhint("You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause.")));

4331 break;

4332 default:

4333 elog(ERROR, "unrecognized commandType: %d",

4334 (int) event);

4335 break;

4336 }

4337 }

4338

4339

4340

4341

4342

4344 (product_queries != NIL || hasUpdate) &&

4345 !updatableview)

4347 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

4348 errmsg("INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules")));

4349

4351 }

4352

4353

4354

4355

4356

4357

4358

4359

4360

4361

4362

4363

4364

4365 if (!instead)

4366 {

4368 {

4369 if (qual_product != NULL)

4370 rewritten = lcons(qual_product, rewritten);

4371 else

4372 rewritten = lcons(parsetree, rewritten);

4373 }

4374 else

4375 {

4376 if (qual_product != NULL)

4377 rewritten = lappend(rewritten, qual_product);

4378 else

4379 rewritten = lappend(rewritten, parsetree);

4380 }

4381 }

4382

4383

4384

4385

4386

4387

4388

4389

4390

4392 {

4393 int qcount = 0;

4394

4395 foreach(lc1, rewritten)

4396 {

4398

4400 qcount++;

4401 }

4402 if (qcount > 1)

4404 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

4405 errmsg("WITH cannot be used in a query that is rewritten by rules into multiple queries")));

4406 }

4407

4408 return rewritten;

4409}

List * lcons(void *datum, List *list)

#define linitial_node(type, l)

bool view_has_instead_trigger(Relation view, CmdType event, List *mergeActionList)

static List * fireRules(Query *parsetree, int rt_index, CmdType event, List *locks, bool *instead_flag, bool *returning_flag, Query **qual_product)

static bool rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti, Relation target_relation, Bitmapset *unused_cols)

static Query * rewriteTargetView(Query *parsetree, Relation view)

static void rewriteValuesRTEToNulls(Query *parsetree, RangeTblEntry *rte)

static List * matchLocks(CmdType event, Relation relation, int varno, Query *parsetree, bool *hasUpdate)

void error_view_not_updatable(Relation view, CmdType command, List *mergeActionList, const char *detail)

static List * rewriteTargetListIU(List *targetList, CmdType commandType, OverridingKind override, Relation target_relation, RangeTblEntry *values_rte, int values_rte_index, Bitmapset **unused_values_attrnos)

References generate_unaccent_rules::action, OnConflictExpr::action, Assert(), castNode, CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_NOTHING, CMD_SELECT, CMD_UPDATE, CMD_UTILITY, Query::commandType, Query::cteList, CommonTableExpr::ctequery, elog, ereport, errcode(), errhint(), errmsg(), ERROR, error_view_not_updatable(), rewrite_event::event, fireRules(), FromExpr::fromlist, gettext_noop, IsA, Query::jointree, lappend(), lcons(), lfirst, lfirst_node, linitial, linitial_node, list_concat(), list_delete_last(), list_length(), matchLocks(), Query::mergeActionList, NIL, NoLock, Query::onConflict, ONCONFLICT_UPDATE, OnConflictExpr::onConflictSet, OVERRIDING_NOT_SET, palloc(), QSRC_NON_INSTEAD_RULE, QSRC_QUAL_INSTEAD_RULE, RelationData::rd_rel, rewrite_event::relation, RelationGetRelationName, RelationGetRelid, Query::returningList, RewriteQuery(), rewriteTargetListIU(), rewriteTargetView(), rewriteValuesRTE(), rewriteValuesRTEToNulls(), rt_fetch, Query::rtable, RTE_RELATION, RTE_SUBQUERY, RTE_VALUES, RangeTblEntry::rtekind, RangeTblRef::rtindex, RangeTblEntry::subquery, table_close(), table_open(), Query::targetList, and view_has_instead_trigger().

Referenced by QueryRewrite(), and RewriteQuery().

rewriteRuleAction()

static Query * rewriteRuleAction ( Query * parsetree, Query * rule_action, Node * rule_qual, int rt_index, CmdType event, bool * returning_flag ) static

Definition at line 351 of file rewriteHandler.c.

357{

358 int current_varno,

359 new_varno;

360 int rt_length;

361 Query *sub_action;

362 Query **sub_action_ptr;

365

367

368

369

370

371

372 rule_action = copyObject(rule_action);

374

375

376

377

380

381 current_varno = rt_index;

384

385

386

387

388

389

390

391

392

394

397

402

403

404

405

406

407

408

409

410

411 foreach(lc, sub_action->rtable)

412 {

414

417 rte->lateral = true;

418 }

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447 {

448 List *rtable_tail = sub_action->rtable;

449 List *perminfos_tail = sub_action->rteperminfos;

450

451

452

453

454

455

457 sub_action->rteperminfos = copyObject(parsetree->rteperminfos);

459 rtable_tail, perminfos_tail);

460 }

461

462

463

464

465

466 if (parsetree->hasSubLinks && !sub_action->hasSubLinks)

467 {

468 foreach(lc, parsetree->rtable)

469 {

471

473 {

475 sub_action->hasSubLinks =

477 break;

479 sub_action->hasSubLinks =

481 break;

483 sub_action->hasSubLinks =

485 break;

487 sub_action->hasSubLinks =

489 break;

490 default:

491

492 break;

493 }

494 sub_action->hasSubLinks |=

496 if (sub_action->hasSubLinks)

497 break;

498 }

499 }

500

501

502

503

504

505

506

507

508 sub_action->hasRowSecurity |= parsetree->hasRowSecurity;

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

525 {

526 bool keeporig;

527 List *newjointree;

528

531 rt_index, 0)) &&

535 if (newjointree != NIL)

536 {

537

538

539

540

541

542

545 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

546 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));

547

550

551

552

553

554

555 if (parsetree->hasSubLinks && !sub_action->hasSubLinks)

556 sub_action->hasSubLinks =

558 }

559 }

560

561

562

563

564

566 {

567

568

569

570

571

572

573

574

575

576

577

578 foreach(lc, parsetree->cteList)

579 {

582

583 foreach(lc2, sub_action->cteList)

584 {

586

589 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

590 errmsg("WITH query name \"%s\" appears in both a rule action and the query being rewritten",

592 }

593 }

594

595

598

599 sub_action->hasRecursive |= parsetree->hasRecursive;

600 sub_action->hasModifyingCTE |= parsetree->hasModifyingCTE;

601

602

603

604

605

606

607

608

609

610

611

612

613

614 if (sub_action->hasModifyingCTE && rule_action != sub_action)

616 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

617 errmsg("INSERT ... SELECT rule actions are not supported for queries having data-modifying statements in WITH")));

618 }

619

620

621

622

623

624

625 AddQual(sub_action, rule_qual);

626

628

629

630

631

632

633

634

635

636

639 {

640 sub_action = (Query *)

642 new_varno,

643 0,

646 sub_action->resultRelation,

650 current_varno,

651 NULL);

652 if (sub_action_ptr)

653 *sub_action_ptr = sub_action;

654 else

655 rule_action = sub_action;

656 }

657

658

659

660

661

662

663

667 {

668 if (*returning_flag)

670 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

671 errmsg("cannot have RETURNING lists in multiple rules")));

672 *returning_flag = true;

675 parsetree->resultRelation,

676 0,

677 rt_fetch(parsetree->resultRelation,

680 rule_action->resultRelation,

682 0,

683 &rule_action->hasSubLinks);

684

685

686 rule_action->returningOldAlias = parsetree->returningOldAlias;

687 rule_action->returningNewAlias = parsetree->returningNewAlias;

688

689

690

691

692

693 if (parsetree->hasSubLinks && !rule_action->hasSubLinks)

694 rule_action->hasSubLinks =

696 }

697

698 return rule_action;

699}

static List * adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)

void OffsetVarNodes(Node *node, int offset, int sublevels_up)

bool checkExprHasSubLink(Node *node)

void CombineRangeTables(List **dst_rtable, List **dst_perminfos, List *src_rtable, List *src_perminfos)

void AddQual(Query *parsetree, Node *qual)

Query * getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)

@ REPLACEVARS_REPORT_ERROR

bool contain_vars_of_level(Node *node, int levelsup)

References acquireLocksOnSubLinks(), AcquireRewriteLocks(), AddQual(), adjustJoinTreeList(), Assert(), ChangeVarNodes(), checkExprHasSubLink(), CMD_INSERT, CMD_UPDATE, CMD_UTILITY, CombineRangeTables(), Query::commandType, contain_vars_of_level(), copyObject, Query::cteList, CommonTableExpr::ctename, ereport, errcode(), errmsg(), ERROR, acquireLocksOnSubLinks_context::for_execute, FromExpr::fromlist, RangeTblEntry::functions, getInsertSelectQuery(), Query::jointree, lfirst, list_concat(), list_length(), NIL, OffsetVarNodes(), PRS2_NEW_VARNO, PRS2_OLD_VARNO, FromExpr::quals, rangeTableEntry_used(), REPLACEVARS_CHANGE_VARNO, REPLACEVARS_REPORT_ERROR, REPLACEVARS_SUBSTITUTE_NULL, ReplaceVarsFromTargetList(), Query::returningList, rt_fetch, Query::rtable, RTE_FUNCTION, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, Query::setOperations, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, Query::targetList, and RangeTblEntry::values_lists.

Referenced by fireRules().

rewriteTargetListIU()

Definition at line 772 of file rewriteHandler.c.

779{

784 int attrno,

785 next_junk_attrno,

786 numattrs;

788 Bitmapset *default_only_cols = NULL;

789

790

791

792

793

794

795

796

797

798

801 next_junk_attrno = numattrs + 1;

802

803 foreach(temp, targetList)

804 {

806

807 if (!old_tle->resjunk)

808 {

809

810 attrno = old_tle->resno;

811 if (attrno < 1 || attrno > numattrs)

812 elog(ERROR, "bogus resno %d in targetlist", attrno);

814

815

816 if (att_tup->attisdropped)

817 continue;

818

819

820 new_tles[attrno - 1] =

822 new_tles[attrno - 1],

823 NameStr(att_tup->attname));

824 }

825 else

826 {

827

828

829

830

831

832

833

834

835

836

837 if (old_tle->resno != next_junk_attrno)

838 {

840 old_tle->resno = next_junk_attrno;

841 }

842 junk_tlist = lappend(junk_tlist, old_tle);

843 next_junk_attrno++;

844 }

845 }

846

847 for (attrno = 1; attrno <= numattrs; attrno++)

848 {

849 TargetEntry *new_tle = new_tles[attrno - 1];

850 bool apply_default;

851

853

854

855 if (att_tup->attisdropped)

856 continue;

857

858

859

860

861

862

863 apply_default = ((new_tle == NULL && commandType == CMD_INSERT) ||

865

867 {

868 int values_attrno = 0;

869

870

871 if (values_rte && new_tle && IsA(new_tle->expr, Var))

872 {

874

875 if (var->varno == values_rte_index)

876 values_attrno = var->varattno;

877 }

878

879

880

881

882

883

884 if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS && !apply_default)

885 {

887 apply_default = true;

889 {

890

891

892

893

894

895

896 if (values_attrno != 0)

897 {

898 if (default_only_cols == NULL)

900

901 if (bms_is_member(values_attrno, default_only_cols))

902 apply_default = true;

903 }

904

905 if (!apply_default)

907 (errcode(ERRCODE_GENERATED_ALWAYS),

908 errmsg("cannot insert a non-DEFAULT value into column \"%s\"",

909 NameStr(att_tup->attname)),

910 errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS.",

911 NameStr(att_tup->attname)),

912 errhint("Use OVERRIDING SYSTEM VALUE to override.")));

913 }

914 }

915

916

917

918

919

920

921 if (att_tup->attidentity == ATTRIBUTE_IDENTITY_BY_DEFAULT &&

923 apply_default = true;

924

925

926

927

928

929 if (att_tup->attgenerated && !apply_default)

930 {

931

932

933

934

935 if (values_attrno != 0)

936 {

937 if (default_only_cols == NULL)

939

940 if (bms_is_member(values_attrno, default_only_cols))

941 apply_default = true;

942 }

943

944 if (!apply_default)

946 (errcode(ERRCODE_GENERATED_ALWAYS),

947 errmsg("cannot insert a non-DEFAULT value into column \"%s\"",

948 NameStr(att_tup->attname)),

949 errdetail("Column \"%s\" is a generated column.",

950 NameStr(att_tup->attname))));

951 }

952

953

954

955

956

957

958 if (values_attrno != 0 && apply_default && unused_values_attrnos)

959 *unused_values_attrnos = bms_add_member(*unused_values_attrnos,

960 values_attrno);

961 }

962

963

964

965

966

967

969 {

970 if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS &&

971 new_tle && !apply_default)

973 (errcode(ERRCODE_GENERATED_ALWAYS),

974 errmsg("column \"%s\" can only be updated to DEFAULT",

975 NameStr(att_tup->attname)),

976 errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS.",

977 NameStr(att_tup->attname))));

978

979 if (att_tup->attgenerated && new_tle && !apply_default)

981 (errcode(ERRCODE_GENERATED_ALWAYS),

982 errmsg("column \"%s\" can only be updated to DEFAULT",

983 NameStr(att_tup->attname)),

984 errdetail("Column \"%s\" is a generated column.",

985 NameStr(att_tup->attname))));

986 }

987

988 if (att_tup->attgenerated)

989 {

990

991

992

993

994 new_tle = NULL;

995 }

996 else if (apply_default)

997 {

998 Node *new_expr;

999

1001

1002

1003

1004

1005

1006

1007

1008

1009 if (!new_expr)

1010 {

1012 new_tle = NULL;

1013 else

1015 att_tup->atttypmod,

1016 att_tup->attcollation,

1017 att_tup->attlen,

1018 att_tup->attbyval);

1019 }

1020

1021 if (new_expr)

1023 attrno,

1025 false);

1026 }

1027

1028 if (new_tle)

1029 new_tlist = lappend(new_tlist, new_tle);

1030 }

1031

1032 pfree(new_tles);

1033

1034 return list_concat(new_tlist, junk_tlist);

1035}

bool bms_is_member(int x, const Bitmapset *a)

if(TABLE==NULL||TABLE_index==NULL)

void pfree(void *pointer)

void * palloc0(Size size)

Node * coerce_null_to_domain(Oid typid, int32 typmod, Oid collation, int typlen, bool typbyval)

@ OVERRIDING_SYSTEM_VALUE

#define RelationGetNumberOfAttributes(relation)

static TargetEntry * process_matched_tle(TargetEntry *src_tle, TargetEntry *prior_tle, const char *attrName)

static Bitmapset * findDefaultOnlyColumns(RangeTblEntry *rte)

References bms_add_member(), bms_is_member(), build_column_default(), CMD_INSERT, CMD_UPDATE, coerce_null_to_domain(), elog, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, TargetEntry::expr, findDefaultOnlyColumns(), flatCopyTargetEntry(), if(), IsA, lappend(), lfirst, list_concat(), makeTargetEntry(), NameStr, NIL, OVERRIDING_SYSTEM_VALUE, OVERRIDING_USER_VALUE, palloc0(), pfree(), process_matched_tle(), pstrdup(), RelationData::rd_att, RelationGetNumberOfAttributes, TargetEntry::resno, TupleDescAttr(), Var::varattno, and Var::varno.

Referenced by RewriteQuery().

rewriteTargetView()

Definition at line 3213 of file rewriteHandler.c.

3214{

3215 Query *viewquery;

3216 bool insert_or_update;

3217 const char *auto_update_detail;

3219 int base_rt_index;

3220 int new_rt_index;

3228 List *view_targetlist;

3230

3231

3232

3233

3234

3235

3236

3237

3239

3240

3241 view_rte = rt_fetch(parsetree->resultRelation, parsetree->rtable);

3243

3244

3245

3246

3247

3248

3249 insert_or_update =

3252

3254 {

3256 {

3259 {

3260 insert_or_update = true;

3261 break;

3262 }

3263 }

3264 }

3265

3266

3270 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

3271 errmsg("access to non-system view \"%s\" is restricted",

3273

3274

3275

3276

3277

3278

3279

3280 auto_update_detail =

3282

3283 if (auto_update_detail)

3287 auto_update_detail);

3288

3289

3290

3291

3292

3293 if (insert_or_update)

3294 {

3296 char *non_updatable_col;

3297

3298

3299

3300

3301

3302

3303

3304

3305

3306

3307

3310

3312 {

3314

3315 if (!tle->resjunk)

3318 }

3319

3321 {

3323 {

3325

3326 if (!tle->resjunk)

3329 }

3330 }

3331

3333 {

3336 {

3338 {

3339 if (!tle->resjunk)

3342 }

3343 }

3344 }

3345

3347 modified_cols,

3348 NULL,

3349 &non_updatable_col);

3350 if (auto_update_detail)

3351 {

3352

3353

3354

3355

3357 {

3360 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3361 errmsg("cannot insert into column \"%s\" of view \"%s\"",

3362 non_updatable_col,

3365 break;

3368 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3369 errmsg("cannot update column \"%s\" of view \"%s\"",

3370 non_updatable_col,

3373 break;

3376 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3377 errmsg("cannot merge into column \"%s\" of view \"%s\"",

3378 non_updatable_col,

3381 break;

3382 default:

3383 elog(ERROR, "unrecognized CmdType: %d",

3385 break;

3386 }

3387 }

3388 }

3389

3390

3391

3392

3393

3394

3395

3396

3398 {

3400 {

3404 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

3405 errmsg("cannot merge into view \"%s\"",

3407 errdetail("MERGE is not supported for views with INSTEAD OF triggers for some actions but not all."),

3408 errhint("To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers."));

3409 }

3410 }

3411

3412

3413

3414

3415

3418

3419 base_rt_index = rtr->rtindex;

3420 base_rte = rt_fetch(base_rt_index, viewquery->rtable);

3423

3424

3425

3426

3427

3428

3429

3430

3432

3433

3434

3435

3436

3437 base_rte->relkind = base_rel->rd_rel->relkind;

3438

3439

3440

3441

3442

3443

3444

3445 if (viewquery->hasSubLinks)

3446 {

3448

3452 }

3453

3454

3455

3456

3457

3458

3459

3460

3461

3462

3463

3464

3465 new_rte = base_rte;

3467

3470

3471

3472

3473

3474

3476 new_rte->inh = false;

3477

3478

3479

3480

3481

3482

3483

3484

3485

3486 view_targetlist = viewquery->targetList;

3487

3489 base_rt_index,

3490 new_rt_index,

3491 0);

3492

3493

3494

3495

3496

3497

3498

3499

3500

3501

3502

3503

3504

3505

3506

3507

3508

3509

3510

3511

3512 new_rte->perminfoindex = 0;

3516 else

3519

3520

3521

3522

3523

3524

3525

3526

3527

3528

3529

3530

3531

3532

3533

3534

3535

3536

3537

3538

3539

3540

3541

3542

3543

3546

3548

3551

3554

3555

3556

3557

3558

3559

3560 new_rte->securityQuals = view_rte->securityQuals;

3561 view_rte->securityQuals = NIL;

3562

3563

3564

3565

3566

3567 parsetree = (Query *)

3569 parsetree->resultRelation,

3570 0,

3571 view_rte,

3572 view_targetlist,

3573 new_rt_index,

3575 0,

3576 NULL);

3577

3578

3579

3580

3581

3582

3583

3585 parsetree->resultRelation,

3586 new_rt_index,

3587 0);

3588 Assert(parsetree->resultRelation == new_rt_index);

3589

3590

3591

3592

3593

3594

3595

3596

3597

3598

3599

3601 {

3603 {

3606

3607 if (tle->resjunk)

3608 continue;

3609

3611 if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var))

3612 tle->resno = ((Var *) view_tle->expr)->varattno;

3613 else

3614 elog(ERROR, "attribute number %d not found in view targetlist",

3616 }

3617

3619 {

3622 {

3624 {

3626

3627 if (tle->resjunk)

3628 continue;

3629

3631 if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var))

3632 tle->resno = ((Var *) view_tle->expr)->varattno;

3633 else

3634 elog(ERROR, "attribute number %d not found in view targetlist",

3636 }

3637 }

3638 }

3639 }

3640

3641

3642

3643

3644

3647 {

3648 Index old_exclRelIndex,

3649 new_exclRelIndex;

3652 List *tmp_tlist;

3653

3654

3655

3656

3657

3658

3660 {

3663

3664 if (tle->resjunk)

3665 continue;

3666

3668 if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var))

3669 tle->resno = ((Var *) view_tle->expr)->varattno;

3670 else

3671 elog(ERROR, "attribute number %d not found in view targetlist",

3673 }

3674

3675

3676

3677

3678

3679

3680

3681

3682

3684

3686 base_rel,

3689 false, false);

3690 new_exclRte = new_exclNSItem->p_rte;

3691 new_exclRte->relkind = RELKIND_COMPOSITE_TYPE;

3692

3693 new_exclRte->perminfoindex = 0;

3694

3698

3699

3700

3701

3702

3705

3706

3707

3708

3709

3710

3711

3712

3713

3714 tmp_tlist = copyObject(view_targetlist);

3715

3717 new_exclRelIndex, 0);

3718

3721 old_exclRelIndex,

3722 0,

3723 view_rte,

3724 tmp_tlist,

3725 new_rt_index,

3727 0,

3728 &parsetree->hasSubLinks);

3729 }

3730

3731

3732

3733

3734

3735

3736

3737

3738

3739

3740

3741

3742

3745 {

3747

3748

3749

3750

3751

3752

3754

3755 ChangeVarNodes(viewqual, base_rt_index, new_rt_index, 0);

3756

3758 {

3759

3760

3761

3762

3763

3764

3765

3766

3767 new_rte = rt_fetch(new_rt_index, parsetree->rtable);

3768 new_rte->securityQuals = lcons(viewqual, new_rte->securityQuals);

3769

3770

3771

3772

3773

3774

3775

3776

3777

3778

3779 if (!parsetree->hasSubLinks)

3781 }

3782 else

3784 }

3785

3786

3787

3788

3789

3790

3791

3792 if (insert_or_update)

3793 {

3796

3797

3798

3799

3800

3801

3802

3803

3804

3805 if (parsetree->withCheckOptions != NIL)

3806 {

3809

3811 {

3812 has_wco = true;

3813 cascaded = true;

3814 }

3815 }

3816

3817

3818

3819

3820

3821

3822

3823

3824

3825

3826 if (has_wco && (cascaded || viewquery->jointree->quals != NULL))

3827 {

3829

3834 wco->qual = NULL;

3836

3837 parsetree->withCheckOptions = lcons(wco,

3838 parsetree->withCheckOptions);

3839

3841 {

3844

3845

3846

3847

3848

3849

3850

3851 if (!parsetree->hasSubLinks &&

3854 }

3855 }

3856 }

3857

3859

3860 return parsetree;

3861}

Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)

ParseState * make_parsestate(ParseState *parentParseState)

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

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

List * BuildOnConflictExcludedTargetlist(Relation targetrel, Index exclRelIndex)

#define RelationHasCheckOption(relation)

#define RelationHasSecurityInvoker(relation)

#define RelationHasCascadedCheckOption(relation)

References _, acquireLocksOnSubLinks(), generate_unaccent_rules::action, OnConflictExpr::action, AddQual(), addRangeTableEntryForRelation(), addRTEPermissionInfo(), adjust_view_column_set(), Assert(), bms_add_member(), bms_is_empty, bms_union(), BuildOnConflictExcludedTargetlist(), WithCheckOption::cascaded, ChangeVarNodes(), RTEPermissionInfo::checkAsUser, checkExprHasSubLink(), CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_NOTHING, CMD_UPDATE, Query::commandType, copyObject, elog, ereport, errcode(), errdetail(), errdetail_internal(), errhint(), errmsg(), ERROR, error_view_not_updatable(), OnConflictExpr::exclRelIndex, OnConflictExpr::exclRelTlist, TargetEntry::expr, FirstLowInvalidHeapAttributeNumber, FirstNormalObjectId, acquireLocksOnSubLinks_context::for_execute, foreach_node, FromExpr::fromlist, get_tle_by_resno(), get_view_query(), getRTEPermissionInfo(), RangeTblEntry::inh, RTEPermissionInfo::insertedCols, InvalidOid, IsA, Query::jointree, WithCheckOption::kind, lappend(), lcons(), lfirst, linitial, linitial_node, list_length(), make_parsestate(), makeAlias(), makeNode, Query::mergeActionList, NIL, NoLock, Query::onConflict, ONCONFLICT_UPDATE, OnConflictExpr::onConflictSet, ParseNamespaceItem::p_rte, WithCheckOption::polname, pstrdup(), QTW_IGNORE_RC_SUBQUERIES, WithCheckOption::qual, FromExpr::quals, query_tree_walker, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RelationHasCascadedCheckOption, RelationHasCheckOption, RelationHasSecurityInvoker, RelationIsSecurityView, WithCheckOption::relname, REPLACEVARS_REPORT_ERROR, ReplaceVarsFromTargetList(), RTEPermissionInfo::requiredPerms, TargetEntry::resno, restrict_nonsystem_relation_kind, RESTRICT_RELKIND_VIEW, RowExclusiveLock, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, RangeTblRef::rtindex, RTEPermissionInfo::selectedCols, table_close(), table_open(), Query::targetList, unlikely, RTEPermissionInfo::updatedCols, view_cols_are_auto_updatable(), view_has_instead_trigger(), view_query_is_auto_updatable(), and WCO_VIEW_CHECK.

Referenced by RewriteQuery().

rewriteValuesRTE()

Definition at line 1412 of file rewriteHandler.c.

1415{

1416 List *newValues;

1418 bool isAutoUpdatableView;

1419 bool allReplaced;

1420 int numattrs;

1421 int *attrnos;

1422

1423

1426

1427

1428

1429

1430

1431

1433 return true;

1434

1435

1436

1437

1438

1439

1440

1441

1443 attrnos = (int *) palloc0(numattrs * sizeof(int));

1444

1446 {

1448

1450 {

1452

1454 {

1456

1457 Assert(attrno >= 1 && attrno <= numattrs);

1458 attrnos[attrno - 1] = tle->resno;

1459 }

1460 }

1461 }

1462

1463

1464

1465

1466

1467

1468 isAutoUpdatableView = false;

1469 if (target_relation->rd_rel->relkind == RELKIND_VIEW &&

1471 {

1472 List *locks;

1473 bool hasUpdate;

1474 bool found;

1476

1477

1479 parsetree->resultRelation, parsetree, &hasUpdate);

1480

1481 found = false;

1482 foreach(l, locks)

1483 {

1485

1487 rule_lock->qual == NULL)

1488 {

1489 found = true;

1490 break;

1491 }

1492 }

1493

1494

1495

1496

1497

1498

1499 if (!found)

1500 isAutoUpdatableView = true;

1501 }

1502

1503 newValues = NIL;

1504 allReplaced = true;

1506 {

1510 int i;

1511

1513

1514 i = 0;

1515 foreach(lc2, sublist)

1516 {

1518 int attrno = attrnos[i++];

1519

1521 {

1523 Node *new_expr;

1524

1525

1526

1527

1528

1529

1531 {

1533

1534 newList = lappend(newList,

1536 def->typeMod,

1537 def->collation));

1538 continue;

1539 }

1540

1541 if (attrno == 0)

1542 elog(ERROR, "cannot set value in column %d to DEFAULT", i);

1543 Assert(attrno > 0 && attrno <= target_relation->rd_att->natts);

1545

1546 if (!att_tup->attisdropped)

1548 else

1549 new_expr = NULL;

1550

1551

1552

1553

1554

1555

1556 if (!new_expr)

1557 {

1558 if (isAutoUpdatableView)

1559 {

1560

1561 newList = lappend(newList, col);

1562 allReplaced = false;

1563 continue;

1564 }

1565

1567 att_tup->atttypmod,

1568 att_tup->attcollation,

1569 att_tup->attlen,

1570 att_tup->attbyval);

1571 }

1572 newList = lappend(newList, new_expr);

1573 }

1574 else

1575 newList = lappend(newList, col);

1576 }

1577 newValues = lappend(newValues, newList);

1578 }

1580

1582

1583 return allReplaced;

1584}

Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)

static bool searchForDefault(RangeTblEntry *rte)

References Assert(), bms_is_member(), build_column_default(), CMD_INSERT, coerce_null_to_domain(), Query::commandType, elog, ERROR, TargetEntry::expr, i, if(), IsA, RewriteRule::isInstead, lappend(), lfirst, linitial, list_length(), makeNullConst(), matchLocks(), NIL, palloc0(), pfree(), RewriteRule::qual, RelationData::rd_att, RelationData::rd_rel, TargetEntry::resno, RTE_VALUES, RangeTblEntry::rtekind, searchForDefault(), Query::targetList, TupleDescAttr(), SetToDefault::typeId, RangeTblEntry::values_lists, Var::varattno, Var::varno, and view_has_instead_trigger().

Referenced by RewriteQuery().

rewriteValuesRTEToNulls()

Definition at line 1597 of file rewriteHandler.c.

1598{

1599 List *newValues;

1601

1602 newValues = NIL;

1604 {

1608

1609 foreach(lc2, sublist)

1610 {

1612

1614 {

1616

1618 def->typeMod,

1619 def->collation));

1620 }

1621 else

1622 newList = lappend(newList, col);

1623 }

1624 newValues = lappend(newValues, newList);

1625 }

1627}

References IsA, lappend(), lfirst, makeNullConst(), NIL, SetToDefault::typeId, and RangeTblEntry::values_lists.

Referenced by RewriteQuery().

searchForDefault()

view_col_is_auto_updatable()

view_cols_are_auto_updatable()

static const char * view_cols_are_auto_updatable ( Query * viewquery, Bitmapset * required_cols, Bitmapset ** updatable_cols, char ** non_updatable_col ) static

Definition at line 2780 of file rewriteHandler.c.

2784{

2788

2789

2790

2791

2792

2795

2796

2797 if (updatable_cols != NULL)

2798 *updatable_cols = NULL;

2799 if (non_updatable_col != NULL)

2800 *non_updatable_col = NULL;

2801

2802

2804 foreach(cell, viewquery->targetList)

2805 {

2807 const char *col_update_detail;

2808

2809 col++;

2811

2812 if (col_update_detail == NULL)

2813 {

2814

2815 if (updatable_cols != NULL)

2816 *updatable_cols = bms_add_member(*updatable_cols, col);

2817 }

2819 {

2820

2821 if (non_updatable_col != NULL)

2822 *non_updatable_col = tle->resname;

2823 return col_update_detail;

2824 }

2825 }

2826

2827 return NULL;

2828}

static const char * view_col_is_auto_updatable(RangeTblRef *rtr, TargetEntry *tle)

References Assert(), bms_add_member(), bms_is_member(), FirstLowInvalidHeapAttributeNumber, FromExpr::fromlist, Query::jointree, lfirst, linitial_node, list_length(), Query::targetList, and view_col_is_auto_updatable().

Referenced by relation_is_updatable(), and rewriteTargetView().

view_has_instead_trigger()

Definition at line 2520 of file rewriteHandler.c.

2521{

2523

2524 switch (event)

2525 {

2528 return true;

2529 break;

2532 return true;

2533 break;

2536 return true;

2537 break;

2540 {

2541 switch (action->commandType)

2542 {

2545 return false;

2546 break;

2549 return false;

2550 break;

2553 return false;

2554 break;

2556

2557 break;

2558 default:

2559 elog(ERROR, "unrecognized commandType: %d", action->commandType);

2560 break;

2561 }

2562 }

2563 return true;

2564 default:

2565 elog(ERROR, "unrecognized CmdType: %d", (int) event);

2566 break;

2567 }

2568 return false;

2569}

References generate_unaccent_rules::action, CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_NOTHING, CMD_UPDATE, elog, ERROR, foreach_node, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, and RelationData::trigdesc.

Referenced by CheckValidResultRel(), RewriteQuery(), rewriteTargetView(), and rewriteValuesRTE().

view_query_is_auto_updatable()

const char * view_query_is_auto_updatable ( Query * viewquery,
bool check_cols
)

Definition at line 2632 of file rewriteHandler.c.

2633{

2636

2637

2638

2639

2640

2641

2642

2643

2644

2645

2646

2647

2648

2649

2650

2651

2652

2653

2654

2655

2656

2657

2658

2659

2660

2661

2662

2663

2664

2665

2666

2667

2668

2670 return gettext_noop("Views containing DISTINCT are not automatically updatable.");

2671

2673 return gettext_noop("Views containing GROUP BY are not automatically updatable.");

2674

2676 return gettext_noop("Views containing HAVING are not automatically updatable.");

2677

2679 return gettext_noop("Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable.");

2680

2682 return gettext_noop("Views containing WITH are not automatically updatable.");

2683

2685 return gettext_noop("Views containing LIMIT or OFFSET are not automatically updatable.");

2686

2687

2688

2689

2690

2691

2692

2693

2694

2695

2696 if (viewquery->hasAggs)

2697 return gettext_noop("Views that return aggregate functions are not automatically updatable.");

2698

2699 if (viewquery->hasWindowFuncs)

2700 return gettext_noop("Views that return window functions are not automatically updatable.");

2701

2702 if (viewquery->hasTargetSRFs)

2703 return gettext_noop("Views that return set-returning functions are not automatically updatable.");

2704

2705

2706

2707

2708

2710 return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");

2711

2714 return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");

2715

2718 (base_rte->relkind != RELKIND_RELATION &&

2719 base_rte->relkind != RELKIND_FOREIGN_TABLE &&

2720 base_rte->relkind != RELKIND_VIEW &&

2721 base_rte->relkind != RELKIND_PARTITIONED_TABLE))

2722 return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");

2723

2725 return gettext_noop("Views containing TABLESAMPLE are not automatically updatable.");

2726

2727

2728

2729

2730

2731 if (check_cols)

2732 {

2734 bool found;

2735

2736 found = false;

2737 foreach(cell, viewquery->targetList)

2738 {

2740

2742 {

2743 found = true;

2744 break;

2745 }

2746 }

2747

2748 if (!found)

2749 return gettext_noop("Views that have no updatable columns are not automatically updatable.");

2750 }

2751

2752 return NULL;

2753}

References Query::cteList, Query::distinctClause, FromExpr::fromlist, gettext_noop, Query::groupClause, Query::groupingSets, Query::havingQual, IsA, Query::jointree, lfirst, Query::limitCount, Query::limitOffset, linitial, list_length(), NIL, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, RangeTblRef::rtindex, Query::setOperations, RangeTblEntry::tablesample, Query::targetList, and view_col_is_auto_updatable().

Referenced by ATExecSetRelOptions(), DefineView(), relation_is_updatable(), and rewriteTargetView().