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

📄 copy.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*		 * Now compute and insert any defaults available for the columns not		 * provided by the input data.	Anything not processed here or above		 * will remain NULL.		 */		for (i = 0; i < num_defaults; i++)		{			values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,											 &isnull, NULL);			if (!isnull)				nulls[defmap[i]] = ' ';		}		/* Next apply any domain constraints */		if (hasConstraints)		{			ParamExecData *prmdata = &econtext->ecxt_param_exec_vals[0];			for (i = 0; i < num_phys_attrs; i++)			{				ExprState  *exprstate = constraintexprs[i];				if (exprstate == NULL)					continue;	/* no constraint for this attr */				/* Insert current row's value into the Param value */				prmdata->value = values[i];				prmdata->isnull = (nulls[i] == 'n');				/*				 * Execute the constraint expression.  Allow the expression to				 * replace the value (consider e.g. a timestamp precision				 * restriction).				 */				values[i] = ExecEvalExpr(exprstate, econtext,										 &isnull, NULL);				nulls[i] = isnull ? 'n' : ' ';			}		}		/* And now we can form the input tuple. */		tuple = heap_formtuple(tupDesc, values, nulls);		if (cstate->oids && file_has_oids)			HeapTupleSetOid(tuple, loaded_oid);		/* Triggers and stuff need to be invoked in query context. */		MemoryContextSwitchTo(oldcontext);		skip_tuple = false;		/* BEFORE ROW INSERT Triggers */		if (resultRelInfo->ri_TrigDesc &&		  resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)		{			HeapTuple	newtuple;			newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);			if (newtuple == NULL)		/* "do nothing" */				skip_tuple = true;			else if (newtuple != tuple) /* modified by Trigger(s) */			{				heap_freetuple(tuple);				tuple = newtuple;			}		}		if (!skip_tuple)		{			/* Place tuple in tuple slot */			ExecStoreTuple(tuple, slot, InvalidBuffer, false);			/* Check the constraints of the tuple */			if (cstate->rel->rd_att->constr)				ExecConstraints(resultRelInfo, slot, estate);			/* OK, store the tuple and create index entries for it */			simple_heap_insert(cstate->rel, tuple);			if (resultRelInfo->ri_NumIndices > 0)				ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);			/* AFTER ROW INSERT Triggers */			ExecARInsertTriggers(estate, resultRelInfo, tuple);		}	}	/* Done, clean up */	error_context_stack = errcontext.previous;	MemoryContextSwitchTo(oldcontext);	/* Execute AFTER STATEMENT insertion triggers */	ExecASInsertTriggers(estate, resultRelInfo);	/* Handle queued AFTER triggers */	AfterTriggerEndQuery(estate);	pfree(values);	pfree(nulls);	pfree(field_strings);	pfree(in_functions);	pfree(typioparams);	pfree(defmap);	pfree(defexprs);	pfree(constraintexprs);	pfree(force_notnull);	ExecDropSingleTupleTableSlot(slot);	ExecCloseIndices(resultRelInfo);	FreeExecutorState(estate);}/* * Read the next input line and stash it in line_buf, with conversion to * server encoding. * * Result is true if read was terminated by EOF, false if terminated * by newline.	The terminating newline or EOF marker is not included * in the final value of line_buf. */static boolCopyReadLine(CopyState cstate){	bool		result;	/* Reset line_buf to empty */	cstate->line_buf.len = 0;	cstate->line_buf.data[0] = '\0';	/* Mark that encoding conversion hasn't occurred yet */	cstate->line_buf_converted = false;	/* Parse data and transfer into line_buf */	if (cstate->csv_mode)		result = CopyReadLineCSV(cstate);	else		result = CopyReadLineText(cstate);	if (result)	{		/*		 * Reached EOF.  In protocol version 3, we should ignore anything		 * after \. up to the protocol end of copy data.  (XXX maybe better		 * not to treat \. as special?)		 */		if (cstate->copy_dest == COPY_NEW_FE)		{			do			{				cstate->raw_buf_index = cstate->raw_buf_len;			} while (CopyLoadRawBuf(cstate));		}	}	else	{		/*		 * If we didn't hit EOF, then we must have transferred the EOL marker		 * to line_buf along with the data.  Get rid of it.		 */		switch (cstate->eol_type)		{			case EOL_NL:				Assert(cstate->line_buf.len >= 1);				Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');				cstate->line_buf.len--;				cstate->line_buf.data[cstate->line_buf.len] = '\0';				break;			case EOL_CR:				Assert(cstate->line_buf.len >= 1);				Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\r');				cstate->line_buf.len--;				cstate->line_buf.data[cstate->line_buf.len] = '\0';				break;			case EOL_CRNL:				Assert(cstate->line_buf.len >= 2);				Assert(cstate->line_buf.data[cstate->line_buf.len - 2] == '\r');				Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');				cstate->line_buf.len -= 2;				cstate->line_buf.data[cstate->line_buf.len] = '\0';				break;			case EOL_UNKNOWN:				/* shouldn't get here */				Assert(false);				break;		}	}	/* Done reading the line.  Convert it to server encoding. */	if (cstate->need_transcoding)	{		char	   *cvt;		cvt = pg_client_to_server(cstate->line_buf.data,								  cstate->line_buf.len);		if (cvt != cstate->line_buf.data)		{			/* transfer converted data back to line_buf */			cstate->line_buf.len = 0;			cstate->line_buf.data[0] = '\0';			appendBinaryStringInfo(&cstate->line_buf, cvt, strlen(cvt));			pfree(cvt);		}	}	/* Now it's safe to use the buffer in error messages */	cstate->line_buf_converted = true;	return result;}/* * CopyReadLineText - inner loop of CopyReadLine for non-CSV mode * * If you need to change this, better look at CopyReadLineCSV too */static boolCopyReadLineText(CopyState cstate){	bool		result;	char	   *copy_raw_buf;	int			raw_buf_ptr;	int			copy_buf_len;	bool		need_data;	bool		hit_eof;	char		s[2];	s[1] = 0;	/* set default status */	result = false;	/*	 * The objective of this loop is to transfer the entire next input line	 * into line_buf.  Hence, we only care for detecting newlines (\r and/or	 * \n) and the end-of-copy marker (\.).	 *	 * For backwards compatibility we allow backslashes to escape newline	 * characters.	Backslashes other than the end marker get put into the	 * line_buf, since CopyReadAttributesText does its own escape processing.	 *	 * These four characters, and only these four, are assumed the same in	 * frontend and backend encodings.	 *	 * For speed, we try to move data to line_buf in chunks rather than one	 * character at a time.  raw_buf_ptr points to the next character to	 * examine; any characters from raw_buf_index to raw_buf_ptr have been	 * determined to be part of the line, but not yet transferred to line_buf.	 *	 * For a little extra speed within the loop, we copy raw_buf and	 * raw_buf_len into local variables.	 */	copy_raw_buf = cstate->raw_buf;	raw_buf_ptr = cstate->raw_buf_index;	copy_buf_len = cstate->raw_buf_len;	need_data = false;			/* flag to force reading more data */	hit_eof = false;			/* flag indicating no more data available */	for (;;)	{		int			prev_raw_ptr;		char		c;		/* Load more data if needed */		if (raw_buf_ptr >= copy_buf_len || need_data)		{			/*			 * Transfer any approved data to line_buf; must do this to be sure			 * there is some room in raw_buf.			 */			if (raw_buf_ptr > cstate->raw_buf_index)			{				appendBinaryStringInfo(&cstate->line_buf,									 cstate->raw_buf + cstate->raw_buf_index,									   raw_buf_ptr - cstate->raw_buf_index);				cstate->raw_buf_index = raw_buf_ptr;			}			/*			 * Try to read some more data.	This will certainly reset			 * raw_buf_index to zero, and raw_buf_ptr must go with it.			 */			if (!CopyLoadRawBuf(cstate))				hit_eof = true;			raw_buf_ptr = 0;			copy_buf_len = cstate->raw_buf_len;			/*			 * If we are completely out of data, break out of the loop,			 * reporting EOF.			 */			if (copy_buf_len <= 0)			{				result = true;				break;			}			need_data = false;		}		/* OK to fetch a character */		prev_raw_ptr = raw_buf_ptr;		c = copy_raw_buf[raw_buf_ptr++];		if (c == '\r')		{			/* Check for \r\n on first line, _and_ handle \r\n. */			if (cstate->eol_type == EOL_UNKNOWN ||				cstate->eol_type == EOL_CRNL)			{				/*				 * If need more data, go back to loop top to load it.				 *				 * Note that if we are at EOF, c will wind up as '\0' because				 * of the guaranteed pad of raw_buf.				 */				if (raw_buf_ptr >= copy_buf_len && !hit_eof)				{					raw_buf_ptr = prev_raw_ptr; /* undo fetch */					need_data = true;					continue;				}				c = copy_raw_buf[raw_buf_ptr];				if (c == '\n')				{					raw_buf_ptr++;		/* eat newline */					cstate->eol_type = EOL_CRNL;		/* in case not set yet */				}				else				{					/* found \r, but no \n */					if (cstate->eol_type == EOL_CRNL)						ereport(ERROR,								(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),							 errmsg("literal carriage return found in data"),								 errhint("Use \"\\r\" to represent carriage return.")));					/*					 * if we got here, it is the first line and we didn't find					 * \n, so don't consume the peeked character					 */					cstate->eol_type = EOL_CR;				}			}			else if (cstate->eol_type == EOL_NL)				ereport(ERROR,						(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),						 errmsg("literal carriage return found in data"),					  errhint("Use \"\\r\" to represent carriage return.")));			/* If reach here, we have found the line terminator */			break;		}		if (c == '\n')		{			if (cstate->eol_type == EOL_CR || cstate->eol_type == EOL_CRNL)				ereport(ERROR,						(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),						 errmsg("literal newline found in data"),						 errhint("Use \"\\n\" to represent newline.")));			cstate->eol_type = EOL_NL;	/* in case not set yet */			/* If reach here, we have found the line terminator */			break;		}		if (c == '\\')		{			/*			 * If need more data, go back to loop top to load it.			 */			if (raw_buf_ptr >= copy_buf_len)			{				if (hit_eof)				{					/* backslash just before EOF, treat as data char */					result = true;					break;				}				raw_buf_ptr = prev_raw_ptr;		/* undo fetch */				need_data = true;				continue;			}			/*			 * In non-CSV mode, backslash quotes the following character even			 * if it's a newline, so we always advance to next character			 */			c = copy_raw_buf[raw_buf_ptr++];			if (c == '.')			{				if (cstate->eol_type == EOL_CRNL)				{					if (raw_buf_ptr >= copy_buf_len && !hit_eof)					{						raw_buf_ptr = prev_raw_ptr;		/* undo fetch */						need_data = true;						continue;					}					/* if hit_eof, c will become '\0' */					c = copy_raw_buf[raw_buf_ptr++];					if (c == '\n')						ereport(ERROR,								(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),								 errmsg("end-of-copy marker does not match previous newline style")));					if (c != '\r')						ereport(ERROR,								(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),								 errmsg("end-of-copy marker corrupt")));				}				if (raw_buf_ptr >= copy_buf_len && !hit_eof)				{					raw_buf_ptr = prev_raw_ptr; /* undo fetch */					need_data = true;					continue;				}				/* if hit_eof, c will become '\0' */				c = copy_raw_buf[raw_buf_ptr++];				if (c != '\r' && c != '\n')					ereport(ERROR,							(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),							 errmsg("end-of-copy marker corrupt")));				if ((cstate->eol_type == EOL_NL && c != '\n') ||					(cstate->eol_type == EOL_CRNL && c != '\n') ||					(cstate->eol_type == EOL_CR && c != '\r'))					ereport(ERROR,							(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),							 errmsg("end-of-copy marker does not match previous newline style")));				/*				 * Transfer only the data before the \. into line_buf, then				 * discard the data and the \. sequence.				 */				if (prev_raw_ptr > cstate->raw_buf_index)					appendBinaryStringInfo(&cstate->line_buf,									 cstate->raw_buf + cstate->raw_buf_index,									   prev_raw_ptr - cstate->raw_buf_index);				cstate->raw_buf_index = raw_buf_ptr;				result = true;	/* report EOF */				break;			}		}		/*		 * Do we need to be careful about trailing bytes of multibyte		 * characters?	(See note above about client_only_encoding)		 *		 * We assume here that pg_encoding_mblen only looks at the first byte		 * of the character!		 */		if (cstate->client_only_encoding)		{			

⌨️ 快捷键说明

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