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

📄 postgres.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * postgres.c *	  POSTGRES C Backend Interface * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.119 1999/07/02 18:09:27 momjian Exp $ * * NOTES *	  this is the "main" module of the postgres backend and *	  hence the main module of the "traffic cop". * *------------------------------------------------------------------------- */#include <unistd.h>#include <stdio.h>#include <string.h>#include <signal.h>#include <time.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include <sys/param.h>			/* for MAXHOSTNAMELEN on most */#ifndef MAXHOSTNAMELEN#include <netdb.h>				/* for MAXHOSTNAMELEN on some */#endif#ifndef MAXHOSTNAMELEN			/* for MAXHOSTNAMELEN under sco3.2v5.0.2 */#include <sys/socket.h>#endif#include <errno.h>#if HAVE_SYS_SELECT_H#include <sys/select.h>#endif	 /* aix */#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#ifdef __CYGWIN32__#include <getopt.h>#endif#include "postgres.h"#include "miscadmin.h"#include "fmgr.h"#include "access/xact.h"#include "catalog/catname.h"#include "commands/async.h"#include "executor/execdebug.h"#include "executor/executor.h"#include "libpq/libpq.h"#include "libpq/pqformat.h"#include "libpq/libpq-be.h"#include "libpq/pqsignal.h"#include "nodes/pg_list.h"#include "nodes/print.h"#include "optimizer/cost.h"#include "optimizer/planner.h"#include "optimizer/prep.h"#include "parser/parser.h"#include "rewrite/rewriteHandler.h"		/* for QueryRewrite() */#include "storage/bufmgr.h"#include "tcop/dest.h"#include "tcop/fastpath.h"#include "tcop/pquery.h"#include "tcop/tcopdebug.h"#include "tcop/tcopprot.h"		/* where declarations for this file go */#include "tcop/utility.h"#include "utils/mcxt.h"#include "utils/rel.h"#include "utils/ps_status.h"#include "utils/temprel.h"#include "nodes/parsenodes.h"#include "../backend/parser/parse.h"#ifdef NOT_USED#include "nodes/relation.h"#endif#ifdef NOT_USED#include "optimizer/xfunc.h"#endif#ifdef NOT_USED#include "nodes/plannodes.h"#endif#ifdef NOT_USED#include "nodes/memnodes.h"#endif#include "utils/trace.h"#ifdef MULTIBYTE#include "mb/pg_wchar.h"#endif/* * Trace flags, see backend/utils/misc/trace.c */#define Verbose				pg_options[TRACE_VERBOSE]#define DebugPrintQuery		pg_options[TRACE_QUERY]#define DebugPrintPlan		pg_options[TRACE_PLAN]#define DebugPrintParse		pg_options[TRACE_PARSE]#define DebugPrintRewrittenParsetree \							pg_options[TRACE_REWRITTEN]#define DebugPPrintPlan		pg_options[TRACE_PRETTY_PLAN]#define DebugPPrintParse	pg_options[TRACE_PRETTY_PARSE]#define DebugPPrintRewrittenParsetree \							pg_options[TRACE_PRETTY_REWRITTEN]#define ShowParserStats		pg_options[TRACE_PARSERSTATS]#define ShowPlannerStats	pg_options[TRACE_PLANNERSTATS]#define ShowExecutorStats	pg_options[TRACE_EXECUTORSTATS]#ifdef LOCK_MGR_DEBUG#define LockDebug			pg_options[TRACE_LOCKS]#endif#define DeadlockCheckTimer	pg_options[OPT_DEADLOCKTIMEOUT]#define HostnameLookup		pg_options[OPT_HOSTLOOKUP]#define ShowPortNumber		pg_options[OPT_SHOWPORTNUMBER]/* ---------------- *		global variables * ---------------- *//*static bool	EnableRewrite = true; , never changes why have it*/CommandDest whereToSendOutput;/* Define status buffer needed by PS_SET_STATUS */PS_DEFINE_BUFFER;extern int	lockingOff;extern int	NBuffers;int			dontExecute = 0;static int	ShowStats;static bool IsEmptyQuery = false;char		relname[80];		/* current relation name *//* note: these declarations had better match tcopprot.h */DLLIMPORT sigjmp_buf Warn_restart;bool		InError;extern int	NBuffers;static int	EchoQuery = 0;		/* default don't echo */time_t		tim;char		pg_pathname[256];FILE	   *StatFp;/* ---------------- *		people who want to use EOF should #define DONTUSENEWLINE in *		tcop/tcopdebug.h * ---------------- */#ifndef TCOP_DONTUSENEWLINEint			UseNewLine = 1;		/* Use newlines query delimiters (the								 * default) */#elseint			UseNewLine = 0;		/* Use EOF as query delimiters */#endif	 /* TCOP_DONTUSENEWLINE *//*** Flags for expensive function optimization -- JMH 3/9/92*/int			XfuncMode = 0;/* * ---------------- *	 Note: _exec_repeat_ defaults to 1 but may be changed *		   by a DEBUG command.	 If you set this to a large *		   number N, run a single query, and then set it *		   back to 1 and run N queries, you can get an idea *		   of how much time is being spent in the parser and *		   planner b/c in the first case this overhead only *		   happens once.  -cim 6/9/91 * ----------------*/int			_exec_repeat_ = 1;/* ---------------------------------------------------------------- *		decls for routines only used in this file * ---------------------------------------------------------------- */static char InteractiveBackend(char *inBuf);static char SocketBackend(char *inBuf);static char ReadCommand(char *inBuf);static void pg_exec_query(char *query_string);/* ---------------------------------------------------------------- *		routines to obtain user input * ---------------------------------------------------------------- *//* ---------------- *	InteractiveBackend() is called for user interactive connections *	the string entered by the user is placed in its parameter inBuf. * ---------------- */static charInteractiveBackend(char *inBuf){	char	   *stuff = inBuf;	/* current place in input buffer */	int			c;				/* character read from getc() */	bool		end = false;	/* end-of-input flag */	bool		backslashSeen = false;	/* have we seen a \ ? */	/* ----------------	 *	display a prompt and obtain input from the user	 * ----------------	 */	printf("backend> ");	fflush(stdout);	for (;;)	{		if (UseNewLine)		{			/* ----------------			 *	if we are using \n as a delimiter, then read			 *	characters until the \n.			 * ----------------			 */			while ((c = getc(stdin)) != EOF)			{				if (c == '\n')				{					if (backslashSeen)					{						stuff--;						continue;					}					else					{						/* keep the newline character */						*stuff++ = '\n';						*stuff++ = '\0';						break;					}				}				else if (c == '\\')					backslashSeen = true;				else					backslashSeen = false;				*stuff++ = (char) c;			}			if (c == EOF)				end = true;		}		else		{			/* ----------------			 *	otherwise read characters until EOF.			 * ----------------			 */			while ((c = getc(stdin)) != EOF)				*stuff++ = (char) c;			if (stuff == inBuf)				end = true;		}		if (end)		{			if (Verbose)				puts("EOF");			IsEmptyQuery = true;			proc_exit(0);		}		/* ----------------		 *	otherwise we have a user query so process it.		 * ----------------		 */		break;	}	/* ----------------	 *	if the query echo flag was given, print the query..	 * ----------------	 */	if (EchoQuery)		printf("query: %s\n", inBuf);	fflush(stdout);	return 'Q';}/* ---------------- *	SocketBackend()		Is called for frontend-backend connections * *	If the input is a query (case 'Q') then the string entered by *	the user is placed in its parameter inBuf. * *	If the input is a fastpath function call (case 'F') then *	the function call is processed in HandleFunctionRequest(). *	(now called from PostgresMain()) * ---------------- */static charSocketBackend(char *inBuf){	char		qtype;	char		result = '\0';	/* ----------------	 *	get input from the frontend	 * ----------------	 */	qtype = '?';	if (pq_getbytes(&qtype, 1) == EOF)	{		/* ------------		 *	when front-end applications quits/dies		 * ------------		 */		proc_exit(0);	}	switch (qtype)	{			/* ----------------			 *	'Q': user entered a query			 * ----------------			 */		case 'Q':			pq_getstr(inBuf, MAX_PARSE_BUFFER);			result = 'Q';			break;			/* ----------------			 *	'F':  calling user/system functions			 * ----------------			 */		case 'F':			pq_getstr(inBuf, MAX_PARSE_BUFFER); /* ignore the rest of the												 * line */			result = 'F';			break;			/* ----------------			 *	'X':  frontend is exiting			 * ----------------			 */		case 'X':			result = 'X';			break;			/* ----------------			 *	otherwise we got garbage from the frontend.			 *			 *	XXX are we certain that we want to do an elog(FATAL) here?			 *		-cim 1/24/90			 * ----------------			 */		default:			elog(FATAL, "Socket command type %c unknown", qtype);			break;	}	return result;}/* ---------------- *		ReadCommand reads a command from either the frontend or *		standard input, places it in inBuf, and returns a char *		representing whether the string is a 'Q'uery or a 'F'astpath *		call. * ---------------- */static charReadCommand(char *inBuf){	if (IsUnderPostmaster)		return SocketBackend(inBuf);	else		return InteractiveBackend(inBuf);}List *pg_parse_and_plan(char *query_string,	/* string to execute */				  Oid *typev,	/* argument types */				  int nargs,	/* number of arguments */				  List **queryListP,	/* returned pointer to the parse										 * trees */				  CommandDest dest,		/* where results should go */				  bool aclOverride){	List	   *querytree_list = NIL;	List	   *plan_list = NIL;	List	   *querytree_list_item;	Query	   *querytree;	Plan	   *plan;	List	   *new_list;	List	   *rewritten;	if (DebugPrintQuery)	{		if (DebugPrintQuery > 3)		{			/* Print the query string as is if query debug level > 3 */			TPRINTF(TRACE_QUERY, "query: %s", query_string);		}		else		{			/* Print condensed query string to fit in one log line */			char		buff[MAX_QUERY_SIZE + 1];			char		c,					   *s,					   *d;			int			n,						is_space = 1;			for (s = query_string, d = buff, n = 0; (c = *s) && (n < MAX_QUERY_SIZE); s++)			{				switch (c)				{					case '\r':					case '\n':					case '\t':						c = ' ';						/* fall through */					case ' ':						if (is_space)							continue;						is_space = 1;						break;					default:						is_space = 0;						break;				}				*d++ = c;				n++;			}			*d = '\0';			TPRINTF(TRACE_QUERY, "query: %s", buff);		}	}	/* ----------------	 *	(1) parse the request string into a list of parse trees	 * ----------------	 */	if (ShowParserStats)		ResetUsage();	querytree_list = parser(query_string, typev, nargs);	if (ShowParserStats)	{		fprintf(stderr, "! Parser Stats:\n");		ShowUsage();	}	/* ----------------	 *	(2) rewrite the queries, as necessary	 *	 *	rewritten queries are collected in new_list.  Note there may be	 *	more or fewer than in the original list.	 * ----------------	 */	new_list = NIL;	foreach(querytree_list_item, querytree_list)	{		querytree = (Query *) lfirst(querytree_list_item);		if (DebugPrintParse || DebugPPrintParse)		{			if (DebugPPrintParse)			{				TPRINTF(TRACE_PRETTY_PARSE, "parser outputs:");				nodeDisplay(querytree);			}			else			{				TPRINTF(TRACE_PARSE, "parser outputs:");				printf("\n%s\n\n", nodeToString(querytree));			}		}		if (querytree->commandType == CMD_UTILITY)		{			/* don't rewrite utilities, just dump 'em into new_list */			new_list = lappend(new_list, querytree);		}		else		{			/* rewrite regular queries */			rewritten = QueryRewrite(querytree);			new_list = nconc(new_list, rewritten);		}	}	querytree_list = new_list;	/*	 * Override ACL checking if requested	 */	if (aclOverride)	{		foreach(querytree_list_item, querytree_list)		{			List	   *l;			querytree = (Query *) lfirst(querytree_list_item);			if (querytree->commandType == CMD_UTILITY)				continue;			foreach(l, querytree->rtable)			{				RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);				rte->skipAcl = TRUE;			}		}	}	if (DebugPrintRewrittenParsetree || DebugPPrintRewrittenParsetree)	{		if (DebugPPrintRewrittenParsetree)		{			TPRINTF(TRACE_PRETTY_REWRITTEN, "after rewriting:");			foreach(querytree_list_item, querytree_list)			{				querytree = (Query *) lfirst(querytree_list_item);				nodeDisplay(querytree);				printf("\n");			}		}		else		{			TPRINTF(TRACE_REWRITTEN, "after rewriting:");			foreach(querytree_list_item, querytree_list)			{				querytree = (Query *) lfirst(querytree_list_item);				printf("\n%s\n\n", nodeToString(querytree));			}		}	}	foreach(querytree_list_item, querytree_list)	{		querytree = (Query *) lfirst(querytree_list_item);		/*		 * For each query that isn't a utility invocation, generate a		 * plan.		 */		if (querytree->commandType != CMD_UTILITY)		{			if (IsAbortedTransactionBlockState())			{				/* ----------------				 *	 the EndCommand() stuff is to tell the frontend				 *	 that the command ended. -cim 6/1/90				 * ----------------				 */				char	   *tag = "*ABORT STATE*";				EndCommand(tag, dest);				elog(NOTICE, "(transaction aborted): %s",					 "queries ignored until END");				if (queryListP)					*queryListP = NIL;				return NIL;			}			if (ShowPlannerStats)				ResetUsage();			/* call that optimizer */			plan = planner(querytree);			if (ShowPlannerStats)			{				fprintf(stderr, "! Planner Stats:\n");				ShowUsage();			}			plan_list = lappend(plan_list, plan);#ifdef INDEXSCAN_PATCH			/* ----------------			 *	Print plan if debugging.			 *	This has been moved here to get debugging output			 *	also for queries in functions.	DZ - 27-8-1996			 * ----------------			 */			if (DebugPrintPlan || DebugPPrintPlan)			{				if (DebugPPrintPlan)				{

⌨️ 快捷键说明

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