ExecScan系列_fgh431的博客-程序员宅基地

技术标签: pgsql11.2源码  

ExecScanFetch



/*
 * -- check interrupts & fetch next potential tuple
 *
 * This routine is concerned with substituting a test tuple if we are
 * inside an EvalPlanQual recheck.  If we aren't, just execute
 * the access method's next-tuple routine.
 */
static inline TupleTableSlot *
ExecScanFetch(ScanState *node,
			  ExecScanAccessMtd accessMtd,
			  ExecScanRecheckMtd recheckMtd)
{
    
	EState	   *estate = node->ps.state;

	CHECK_FOR_INTERRUPTS();

	if (estate->es_epqTuple != NULL)
	{
    
		/*
		 * We are inside an EvalPlanQual recheck.  Return the test tuple if
		 * one is available, after rechecking any access-method-specific
		 * conditions.
		 */
		Index		scanrelid = ((Scan *) node->ps.plan)->scanrelid;

		if (scanrelid == 0)
		{
    
			TupleTableSlot *slot = node->ss_ScanTupleSlot;

			/*
			 * This is a ForeignScan or CustomScan which has pushed down a
			 * join to the remote side.  The recheck method is responsible not
			 * only for rechecking the scan/join quals but also for storing
			 * the correct tuple in the slot.
			 */
			if (!(*recheckMtd) (node, slot))
				ExecClearTuple(slot);	/* would not be returned by scan */
			return slot;
		}
		else if (estate->es_epqTupleSet[scanrelid - 1])
		{
    
			TupleTableSlot *slot = node->ss_ScanTupleSlot;

			/* Return empty slot if we already returned a tuple */
			if (estate->es_epqScanDone[scanrelid - 1])
				return ExecClearTuple(slot);
			/* Else mark to remember that we shouldn't return more */
			estate->es_epqScanDone[scanrelid - 1] = true;

			/* Return empty slot if we haven't got a test tuple */
			if (estate->es_epqTuple[scanrelid - 1] == NULL)
				return ExecClearTuple(slot);

			/* Store test tuple in the plan node's scan slot */
			ExecStoreTuple(estate->es_epqTuple[scanrelid - 1],
						   slot, InvalidBuffer, false);

			/* Check if it meets the access-method conditions */
			if (!(*recheckMtd) (node, slot))
				ExecClearTuple(slot);	/* would not be returned by scan */

			return slot;
		}
	}

	/*
	 * Run the node-type-specific access method function to get the next tuple
	 */
	return (*accessMtd) (node);
}

ExecSeqScan


static TupleTableSlot *
ExecSeqScan(PlanState *pstate)
{
    
	SeqScanState *node = castNode(SeqScanState, pstate);

	return ExecScan(&node->ss,
					(ExecScanAccessMtd) SeqNext,
					(ExecScanRecheckMtd) SeqRecheck);
}

TupIsNull(slot)

/*
 * TupIsNull -- is a TupleTableSlot empty?
 */
#define TupIsNull(slot) \
	((slot) == NULL || (slot)->tts_isempty)


ResetExprContext(econtext)


#define ResetExprContext(econtext) \
	MemoryContextReset((econtext)->ecxt_per_tuple_memory)

MemoryContextReset


/*
 * MemoryContextReset
 *		Release all space allocated within a context and delete all its
 *		descendant contexts (but not the named context itself).
 */
void
MemoryContextReset(MemoryContext context)
{
    
	AssertArg(MemoryContextIsValid(context));

	/* save a function call in common case where there are no children */
	if (context->firstchild != NULL)
		MemoryContextDeleteChildren(context);

	/* save a function call if no pallocs since startup or last reset */
	if (!context->isReset)
		MemoryContextResetOnly(context);
}


ExecScan

/* ----------------------------------------------------------------
 *		Scans the relation using the 'access method' indicated and
 *		returns the next qualifying tuple in the direction specified
 *		in the global variable ExecDirection.
 *		The access method returns the next tuple and ExecScan() is
 *		responsible for checking the tuple returned against the qual-clause.
 *
 *		A 'recheck method' must also be provided that can check an
 *		arbitrary tuple of the relation against any qual conditions
 *		that are implemented internal to the access method.
 *
 *		Conditions:
 *		  -- the "cursor" maintained by the AMI is positioned at the tuple
 *			 returned previously.
 *
 *		Initial States:
 *		  -- the relation indicated is opened for scanning so that the
 *			 "cursor" is positioned before the first qualifying tuple.
 * ----------------------------------------------------------------
 */
TupleTableSlot *
ExecScan(ScanState *node,
		 ExecScanAccessMtd accessMtd,	/* function returning a tuple */
		 ExecScanRecheckMtd recheckMtd)
{
    
	ExprContext *econtext;
	ExprState  *qual;
	ProjectionInfo *projInfo;

	/*
	 * Fetch data from node
	 */
	qual = node->ps.qual;
	projInfo = node->ps.ps_ProjInfo;
	econtext = node->ps.ps_ExprContext;

	/* interrupt checks are in ExecScanFetch */

	/*
	 * If we have neither a qual to check nor a projection to do, just skip
	 * all the overhead and return the raw scan tuple.
	 */
	if (!qual && !projInfo)
	{
    
		ResetExprContext(econtext);
		return ExecScanFetch(node, accessMtd, recheckMtd);
	}

	/*
	 * Reset per-tuple memory context to free any expression evaluation
	 * storage allocated in the previous tuple cycle.
	 */
	ResetExprContext(econtext);

	/*
	 * get a tuple from the access method.  Loop until we obtain a tuple that
	 * passes the qualification.
	 */
	for (;;)
	{
    
		TupleTableSlot *slot;

		slot = ExecScanFetch(node, accessMtd, recheckMtd);

		/*
		 * if the slot returned by the accessMtd contains NULL, then it means
		 * there is nothing more to scan so we just return an empty slot,
		 * being careful to use the projection result slot so it has correct
		 * tupleDesc.
		 */
		if (TupIsNull(slot))
		{
    
			if (projInfo)
				return ExecClearTuple(projInfo->pi_state.resultslot);
			else
				return slot;
		}

		/*
		 * place the current tuple into the expr context
		 */
		econtext->ecxt_scantuple = slot;

		/*
		 * check that the current tuple satisfies the qual-clause
		 *
		 * check for non-null qual here to avoid a function call to ExecQual()
		 * when the qual is null ... saves only a few cycles, but they add up
		 * ...
		 */
		if (qual == NULL || ExecQual(qual, econtext))
		{
    
			/*
			 * Found a satisfactory scan tuple.
			 */
			if (projInfo)
			{
    
				/*
				 * Form a projection tuple, store it in the result tuple slot
				 * and return it.
				 */
				return ExecProject(projInfo);
			}
			else
			{
    
				/*
				 * Here, we aren't projecting, so just return scan tuple.
				 */
				return slot;
			}
		}
		else
			InstrCountFiltered1(node, 1);

		/*
		 * Tuple fails qual, so free per-tuple memory and try again.
		 */
		ResetExprContext(econtext);
	}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhoutianzi12/article/details/106041481

智能推荐

Linux下自动生成 Makefile_zhang_heaven的博客-程序员宅基地

在 Unix 上写程式的人大概都碰过 Makefile,尤其是用 C 来开发程式的人。用 make 来开发和编译程式的确很方便,可是要写出一个 Makefile就不简单了。偏偏介绍 Makefile 的文件不多,GNU Make 那份印出来要几百页的文件,光看完 Overview 就快阵亡了,难怪许多人闻 Unix 色变。本文将介绍如何利用 GNU Autoconf 及 Automake 这两套软

UIAlertView和UIAlertControl_weixin_34384915的博客-程序员宅基地

iOS 8的新特性之一就是让接口更有适应性、更灵活,因此许多视图控制器的实现方式发生了巨大的变化。全新的UIPresentationController 在实现视图控制器间的过渡动画效果和自适应设备尺寸变化效果(比如说旋转)中发挥了重要的作用,它有效地节省了程序员们的工作量(天地良心啊)。还有,某 些旧的UIKit控件也同样发生了许多变化,比如说Alert Views、Action Sheets、...

CPU卡文件_「已注销」的博客-程序员宅基地

一般来说,对存储卡和逻辑加密卡操作,使用接触式IC卡通用读写器;对CPU卡使用CPU卡读写器。所谓“通用读卡器”是指它可以对大多数流行的存储卡和逻辑加密卡操作。而CPU卡由于有ISO/IEC 7816.3/4的规范,其通讯协议、命令格式都是兼容的,被看作是一种卡。当然,也有将“通用读卡器”与CPU读卡器二合一的真正的接触式通用读卡器。   PC端IC卡应用软件编程,要点是了解卡的数据结构和

1.并发编程多进程(理论部分)_changxin7的博客-程序员宅基地

文章目录一 什么是进程二 进程与程序的区别三 并发与并行四 同步\异步and阻塞\非阻塞(重点)五 进程的创建(了解)六 进程的终止(了解)七 进程的层次结构八 进程的状态九 进程并发的实现(了解)一 什么是进程​ 进程:正在进行的一个过程或者说一个任务。而负责执行任务则是cpu。​ 举例(单核+多道,实现多个进程的并发执行):​ 太白金星在一个时间段内有很多任务要做:p...

linux 日志自定义模板,haproxy json 自定义格式日志 并用rsyslog 收集_vjcdtstcjj的博客-程序员宅基地

haproxy的配置日志投送:globallog127.0.0.1 local1 info默认端口是udp514默认日志:defaultslog globallog-format \"local_time\":\"%t\",\"log_type\":\"tcp_log\",\"frontend_name\":\"%f\",\"hostname\":\"%H\",\"clientip\":\...

狂神说--mybatis笔记整理_小小酒馆的掌柜的博客-程序员宅基地_狂神mybatis笔记

Mybatis01-CRUD目录结构java文件实体类Student.java:public class Student { private Integer id; private String name; private Date birthday; set() get() toString()}接口StudentMapper.java:public interface StudentMapper { public List<Stude

随便推点

PL/SQL Developer连接数据库及操控数据库_circlebear1122的博客-程序员宅基地

PL/SQL Developer使用 PL/SQL Developer是一个集成开发环境,由Al...

攻克数据库核心技术壁垒,实现百万级QPS的高吞吐_腾讯云开发者的博客-程序员宅基地

CynosDB是腾讯云自研的新一代高性能高可用的企业级分布式云数据库。融合了传统数据库、云计算与新硬件的优势,100%兼容开源数据库,百万级QPS的高吞吐,不限存储,价格仅为商用数据库的1/10。CynosDB设计出发点:随着云计算2.0时代的来临,在云计算技术和服务的支持下,越来越多的互联网企业业务规模快速扩大,它们对构建于云端的核心基础设施服务—数据库服务提出了更高的要求,如更高的性能、更好的...

多关卡连连看php源码_自己做的一个可以更换图片的连连看游戏(源码)_杉木優子的博客-程序员宅基地

【实例简介】自己做的二次开发,将原来的固定图片的了连连看游戏改为可以自己更换图片的连连看。【实例截图】【核心代码】lianliankan└── lianliankan├── AndroidManifest.xml├── bin│ ├── classes.dex│ ├── com│ │ └── yuxiang│ │ ├── android│ │ │...

素数判定及筛法_Charming Boy的博客-程序员宅基地

文章目录试除法求质数分解质因数埃式筛法线性筛法试除法求质数质数是在大于一的整数中,只能被1 和 它本身整除的数,也叫素数。时间复杂度为O(sqrt(n))#include <iostream>#include <algorithm>using namespace std;int main(){ int n, x; cin >> n ;...

npm WARN config global `--global`, `--local` are deprecated. Use `--location解决方案_樱丸小桃子啊的博客-程序员宅基地

配置node遇到npm WARN config global `--global`, `--local` are deprecated. Use `--location报错的解决方案

给出年、月、日,计算该日是该年的第几天。_邹氏情歌cium的博客-程序员宅基地

给出年、月、日,计算该日是该年的第几天。#include <stdio.h>void date(int y, int m, int d); //定义天数判断函数int main(){ int year, month, day; printf("Please enter Year Month Day: "); //输入年月日...

推荐文章

热门文章

相关标签