⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 execmain.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
					slot = ExecStoreTuple(tuple, slot, InvalidBuffer, true);					goto lreplace;				}			}			return;		default:			elog(ERROR, "Unknown status %u from heap_replace", result);			return;	}	IncrReplaced();	(estate->es_processed)++;	/*	 * Note: instead of having to update the old index tuples associated	 * with the heap tuple, all we do is form and insert new index	 * tuples..  This is because replaces are actually deletes and inserts	 * and index tuple deletion is done automagically by the vaccuum	 * deamon.. All we do is insert new index tuples.  -cim 9/27/89	 */	/*	 * process indices	 *	 * heap_replace updates a tuple in the base relation by invalidating it	 * and then appending a new tuple to the relation.	As a side effect,	 * the tupleid of the new tuple is placed in the new tuple's t_ctid	 * field.  So we now insert index tuples using the new tupleid stored	 * there.	 */	numIndices = resultRelationInfo->ri_NumIndices;	if (numIndices > 0)		ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);	/* AFTER ROW UPDATE Triggers */	if (resultRelationDesc->trigdesc &&	 resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)		ExecARUpdateTriggers(estate, tupleid, tuple);}#ifdef NOT_USEDstatic HeapTupleExecAttrDefault(Relation rel, HeapTuple tuple){	int			ndef = rel->rd_att->constr->num_defval;	AttrDefault *attrdef = rel->rd_att->constr->defval;	ExprContext *econtext = makeNode(ExprContext);	HeapTuple	newtuple;	Node	   *expr;	bool		isnull;	bool		isdone;	Datum		val;	Datum	   *replValue = NULL;	char	   *replNull = NULL;	char	   *repl = NULL;	int			i;	econtext->ecxt_scantuple = NULL;	/* scan tuple slot */	econtext->ecxt_innertuple = NULL;	/* inner tuple slot */	econtext->ecxt_outertuple = NULL;	/* outer tuple slot */	econtext->ecxt_relation = NULL;		/* relation */	econtext->ecxt_relid = 0;	/* relid */	econtext->ecxt_param_list_info = NULL;		/* param list info */	econtext->ecxt_param_exec_vals = NULL;		/* exec param values */	econtext->ecxt_range_table = NULL;	/* range table */	for (i = 0; i < ndef; i++)	{		if (!heap_attisnull(tuple, attrdef[i].adnum))			continue;		expr = (Node *) stringToNode(attrdef[i].adbin);		val = ExecEvalExpr(expr, econtext, &isnull, &isdone);		pfree(expr);		if (isnull)			continue;		if (repl == NULL)		{			repl = (char *) palloc(rel->rd_att->natts * sizeof(char));			replNull = (char *) palloc(rel->rd_att->natts * sizeof(char));			replValue = (Datum *) palloc(rel->rd_att->natts * sizeof(Datum));			MemSet(repl, ' ', rel->rd_att->natts * sizeof(char));		}		repl[attrdef[i].adnum - 1] = 'r';		replNull[attrdef[i].adnum - 1] = ' ';		replValue[attrdef[i].adnum - 1] = val;	}	pfree(econtext);	if (repl == NULL)		return tuple;	newtuple = heap_modifytuple(tuple, rel, replValue, replNull, repl);	pfree(repl);	pfree(tuple);	pfree(replNull);	pfree(replValue);	return newtuple;}#endifstatic char *ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate){	int			ncheck = rel->rd_att->constr->num_check;	ConstrCheck *check = rel->rd_att->constr->check;	ExprContext *econtext = makeNode(ExprContext);	TupleTableSlot *slot = makeNode(TupleTableSlot);	RangeTblEntry *rte = makeNode(RangeTblEntry);	List	   *rtlist;	List	   *qual;	bool		res;	int			i;	slot->val = tuple;	slot->ttc_shouldFree = false;	slot->ttc_descIsNew = true;	slot->ttc_tupleDescriptor = rel->rd_att;	slot->ttc_buffer = InvalidBuffer;	slot->ttc_whichplan = -1;	rte->relname = nameout(&(rel->rd_rel->relname));	rte->refname = rte->relname;	rte->relid = RelationGetRelid(rel);	rte->inh = false;	rte->inFromCl = true;	rtlist = lcons(rte, NIL);	econtext->ecxt_scantuple = slot;	/* scan tuple slot */	econtext->ecxt_innertuple = NULL;	/* inner tuple slot */	econtext->ecxt_outertuple = NULL;	/* outer tuple slot */	econtext->ecxt_relation = rel;		/* relation */	econtext->ecxt_relid = 0;	/* relid */	econtext->ecxt_param_list_info = NULL;		/* param list info */	econtext->ecxt_param_exec_vals = NULL;		/* exec param values */	econtext->ecxt_range_table = rtlist;		/* range table */	if (estate->es_result_relation_constraints == NULL)	{		estate->es_result_relation_constraints =			(List **) palloc(ncheck * sizeof(List *));		for (i = 0; i < ncheck; i++)		{			qual = (List *) stringToNode(check[i].ccbin);			estate->es_result_relation_constraints[i] = qual;		}	}	for (i = 0; i < ncheck; i++)	{		qual = estate->es_result_relation_constraints[i];		res = ExecQual(qual, econtext);		if (!res)			return check[i].ccname;	}	pfree(slot);	pfree(rte->relname);	pfree(rte);	pfree(rtlist);	pfree(econtext);	return (char *) NULL;}voidExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate){	Assert(rel->rd_att->constr);	if (rel->rd_att->constr->has_not_null)	{		int			attrChk;		for (attrChk = 1; attrChk <= rel->rd_att->natts; attrChk++)		{			if (rel->rd_att->attrs[attrChk - 1]->attnotnull && heap_attisnull(tuple, attrChk))				elog(ERROR, "%s: Fail to add null value in not null attribute %s",				  caller, rel->rd_att->attrs[attrChk - 1]->attname.data);		}	}	if (rel->rd_att->constr->num_check > 0)	{		char	   *failed;		if ((failed = ExecRelCheck(rel, tuple, estate)) != NULL)			elog(ERROR, "%s: rejected due to CHECK constraint %s", caller, failed);	}	return;}TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid){	evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;	evalPlanQual *oldepq;	EState	   *epqstate = NULL;	Relation	relation;	Buffer		buffer;	HeapTupleData tuple;	bool		endNode = true;	Assert(rti != 0);	if (epq != NULL && epq->rti == 0)	{		Assert(!(estate->es_useEvalPlan) &&			   epq->estate.es_evalPlanQual == NULL);		epq->rti = rti;		endNode = false;	}	/*	 * If this is request for another RTE - Ra, - then we have to check	 * wasn't PlanQual requested for Ra already and if so then Ra' row was	 * updated again and we have to re-start old execution for Ra and	 * forget all what we done after Ra was suspended. Cool? -:))	 */	if (epq != NULL && epq->rti != rti &&		epq->estate.es_evTuple[rti - 1] != NULL)	{		do		{			/* pop previous PlanQual from the stack */			epqstate = &(epq->estate);			oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;			Assert(oldepq->rti != 0);			/* stop execution */			ExecEndNode(epq->plan, epq->plan);		    epqstate->es_tupleTable->next = 0;			pfree(epqstate->es_evTuple[epq->rti - 1]);			epqstate->es_evTuple[epq->rti - 1] = NULL;			/* push current PQ to freePQ stack */			oldepq->free = epq;			epq = oldepq;		} while (epq->rti != rti);		estate->es_evalPlanQual = (Pointer) epq;	}	/*	 * If we are requested for another RTE then we have to suspend	 * execution of current PlanQual and start execution for new one.	 */	if (epq == NULL || epq->rti != rti)	{		/* try to reuse plan used previously */		evalPlanQual *newepq = (epq != NULL) ? epq->free : NULL;		if (newepq == NULL)		/* first call or freePQ stack is empty */		{			newepq = (evalPlanQual *) palloc(sizeof(evalPlanQual));			/* Init EState */			epqstate = &(newepq->estate);			memset(epqstate, 0, sizeof(EState));			epqstate->type = T_EState;			epqstate->es_direction = ForwardScanDirection;			epqstate->es_snapshot = estate->es_snapshot;			epqstate->es_range_table = estate->es_range_table;			epqstate->es_param_list_info = estate->es_param_list_info;			if (estate->es_origPlan->nParamExec > 0)				epqstate->es_param_exec_vals = (ParamExecData *)					palloc(estate->es_origPlan->nParamExec *						   sizeof(ParamExecData));			epqstate->es_tupleTable =				ExecCreateTupleTable(estate->es_tupleTable->size);			epqstate->es_refcount = estate->es_refcount;			/* ... rest */			newepq->plan = copyObject(estate->es_origPlan);			newepq->free = NULL;			epqstate->es_evTupleNull = (bool *)				palloc(length(estate->es_range_table) * sizeof(bool));			if (epq == NULL)	/* first call */			{				epqstate->es_evTuple = (HeapTuple *)					palloc(length(estate->es_range_table) * sizeof(HeapTuple));				memset(epqstate->es_evTuple, 0,					 length(estate->es_range_table) * sizeof(HeapTuple));			}			else				epqstate->es_evTuple = epq->estate.es_evTuple;		}		else			epqstate = &(newepq->estate);		/* push current PQ to the stack */		epqstate->es_evalPlanQual = (Pointer) epq;		epq = newepq;		estate->es_evalPlanQual = (Pointer) epq;		epq->rti = rti;		endNode = false;	}	epqstate = &(epq->estate);	/*	 * Ok - we're requested for the same RTE (-:)). I'm not sure about	 * ability to use ExecReScan instead of ExecInitNode, so...	 */	if (endNode)	{		ExecEndNode(epq->plan, epq->plan);	    epqstate->es_tupleTable->next = 0;	}	/* free old RTE' tuple */	if (epqstate->es_evTuple[epq->rti - 1] != NULL)	{		pfree(epqstate->es_evTuple[epq->rti - 1]);		epqstate->es_evTuple[epq->rti - 1] = NULL;	}	/* ** fetch tid tuple ** */	if (estate->es_result_relation_info != NULL &&		estate->es_result_relation_info->ri_RangeTableIndex == rti)		relation = estate->es_result_relation_info->ri_RelationDesc;	else	{		List	   *l;		foreach(l, estate->es_rowMark)		{			if (((execRowMark *) lfirst(l))->rti == rti)				break;		}		relation = ((execRowMark *) lfirst(l))->relation;	}	tuple.t_self = *tid;	for (;;)	{		heap_fetch(relation, SnapshotDirty, &tuple, &buffer);		if (tuple.t_data != NULL)		{			TransactionId xwait = SnapshotDirty->xmax;			if (TransactionIdIsValid(SnapshotDirty->xmin))			{				elog(NOTICE, "EvalPlanQual: t_xmin is uncommitted ?!");				Assert(!TransactionIdIsValid(SnapshotDirty->xmin));				elog(ERROR, "Aborting this transaction");			}			/*			 * If tuple is being updated by other transaction then we have			 * to wait for its commit/abort.			 */			if (TransactionIdIsValid(xwait))			{				ReleaseBuffer(buffer);				XactLockTableWait(xwait);				continue;			}			/*			 * Nice! We got tuple - now copy it.			 */			if (epqstate->es_evTuple[epq->rti - 1] != NULL)				pfree(epqstate->es_evTuple[epq->rti - 1]);			epqstate->es_evTuple[epq->rti - 1] = heap_copytuple(&tuple);			ReleaseBuffer(buffer);			break;		}		/*		 * Ops! Invalid tuple. Have to check is it updated or deleted.		 * Note that it's possible to get invalid SnapshotDirty->tid if		 * tuple updated by this transaction. Have we to check this ?		 */		if (ItemPointerIsValid(&(SnapshotDirty->tid)) &&			!(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid))))		{			tuple.t_self = SnapshotDirty->tid;	/* updated ... */			continue;		}		/*		 * Deleted or updated by this transaction. Do not (re-)start		 * execution of this PQ. Continue previous PQ.		 */		oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;		if (oldepq != NULL)		{			Assert(oldepq->rti != 0);			/* push current PQ to freePQ stack */			oldepq->free = epq;			epq = oldepq;			epqstate = &(epq->estate);			estate->es_evalPlanQual = (Pointer) epq;		}		else		{												epq->rti = 0;					/* this is the first (oldest) */			estate->es_useEvalPlan = false;	/* PQ - mark as free and      */			return (NULL);					/* continue Query execution   */		}	}	if (estate->es_origPlan->nParamExec > 0)		memset(epqstate->es_param_exec_vals, 0,			   estate->es_origPlan->nParamExec * sizeof(ParamExecData));	memset(epqstate->es_evTupleNull, false,		   length(estate->es_range_table) * sizeof(bool));    Assert(epqstate->es_tupleTable->next == 0);	ExecInitNode(epq->plan, epqstate, NULL);	/*	 * For UPDATE/DELETE we have to return tid of actual row we're	 * executing PQ for.	 */	*tid = tuple.t_self;	return (EvalPlanQualNext(estate));}static TupleTableSlot *EvalPlanQualNext(EState *estate){	evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;	EState	   *epqstate = &(epq->estate);	evalPlanQual *oldepq;	TupleTableSlot *slot;	Assert(epq->rti != 0);lpqnext:;	slot = ExecProcNode(epq->plan, epq->plan);	/*	 * No more tuples for this PQ. Continue previous one.	 */	if (TupIsNull(slot))	{		ExecEndNode(epq->plan, epq->plan);	    epqstate->es_tupleTable->next = 0;		pfree(epqstate->es_evTuple[epq->rti - 1]);		epqstate->es_evTuple[epq->rti - 1] = NULL;		/* pop old PQ from the stack */		oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;		if (oldepq == (evalPlanQual *) NULL)		{			epq->rti = 0;					/* this is the first (oldest) */			estate->es_useEvalPlan = false;	/* PQ - mark as free and	  */			return (NULL);					/* continue Query execution   */		}		Assert(oldepq->rti != 0);		/* push current PQ to freePQ stack */		oldepq->free = epq;		epq = oldepq;		epqstate = &(epq->estate);		estate->es_evalPlanQual = (Pointer) epq;		goto lpqnext;	}	return (slot);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -