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

📄 pqformat.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * pqformat.c *		Routines for formatting and parsing frontend/backend messages * * Outgoing messages are built up in a StringInfo buffer (which is expansible) * and then sent in a single call to pq_putmessage.  This module provides data * formatting/conversion routines that are needed to produce valid messages. * Note in particular the distinction between "raw data" and "text"; raw data * is message protocol characters and binary values that are not subject to * character set conversion, while text is converted by character encoding * rules. * * Incoming messages are similarly read into a StringInfo buffer, via * pq_getmessage, and then parsed and converted from that using the routines * in this module. * * These same routines support reading and writing of external binary formats * (typsend/typreceive routines).  The conversion routines for individual * data types are exactly the same, only initialization and completion * are different. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * *	$PostgreSQL: pgsql/src/backend/libpq/pqformat.c,v 1.40 2005/10/15 02:49:18 momjian Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES * Message assembly and output: *		pq_beginmessage - initialize StringInfo buffer *		pq_sendbyte		- append a raw byte to a StringInfo buffer *		pq_sendint		- append a binary integer to a StringInfo buffer *		pq_sendint64	- append a binary 8-byte int to a StringInfo buffer *		pq_sendfloat4	- append a float4 to a StringInfo buffer *		pq_sendfloat8	- append a float8 to a StringInfo buffer *		pq_sendbytes	- append raw data to a StringInfo buffer *		pq_sendcountedtext - append a counted text string (with character set conversion) *		pq_sendtext		- append a text string (with conversion) *		pq_sendstring	- append a null-terminated text string (with conversion) *		pq_endmessage	- send the completed message to the frontend * Note: it is also possible to append data to the StringInfo buffer using * the regular StringInfo routines, but this is discouraged since required * character set conversion may not occur. * * typsend support (construct a bytea value containing external binary data): *		pq_begintypsend - initialize StringInfo buffer *		pq_endtypsend	- return the completed string as a "bytea*" * * Special-case message output: *		pq_puttextmessage - generate a character set-converted message in one step *		pq_putemptymessage - convenience routine for message with empty body * * Message parsing after input: *		pq_getmsgbyte	- get a raw byte from a message buffer *		pq_getmsgint	- get a binary integer from a message buffer *		pq_getmsgint64	- get a binary 8-byte int from a message buffer *		pq_getmsgfloat4 - get a float4 from a message buffer *		pq_getmsgfloat8 - get a float8 from a message buffer *		pq_getmsgbytes	- get raw data from a message buffer *		pq_copymsgbytes - copy raw data from a message buffer *		pq_getmsgtext	- get a counted text string (with conversion) *		pq_getmsgstring - get a null-terminated text string (with conversion) *		pq_getmsgend	- verify message fully consumed */#include "postgres.h"#include <errno.h>#include <sys/param.h>#include <netinet/in.h>#include <arpa/inet.h>#ifdef HAVE_ENDIAN_H#include <endian.h>#endif#include "libpq/libpq.h"#include "libpq/pqformat.h"#include "mb/pg_wchar.h"/* -------------------------------- *		pq_beginmessage		- initialize for sending a message * -------------------------------- */voidpq_beginmessage(StringInfo buf, char msgtype){	initStringInfo(buf);	/*	 * We stash the message type into the buffer's cursor field, expecting	 * that the pq_sendXXX routines won't touch it.  We could alternatively	 * make it the first byte of the buffer contents, but this seems easier.	 */	buf->cursor = msgtype;}/* -------------------------------- *		pq_sendbyte		- append a raw byte to a StringInfo buffer * -------------------------------- */voidpq_sendbyte(StringInfo buf, int byt){	appendStringInfoCharMacro(buf, byt);}/* -------------------------------- *		pq_sendbytes	- append raw data to a StringInfo buffer * -------------------------------- */voidpq_sendbytes(StringInfo buf, const char *data, int datalen){	appendBinaryStringInfo(buf, data, datalen);}/* -------------------------------- *		pq_sendcountedtext - append a counted text string (with character set conversion) * * The data sent to the frontend by this routine is a 4-byte count field * followed by the string.	The count includes itself or not, as per the * countincludesself flag (pre-3.0 protocol requires it to include itself). * The passed text string need not be null-terminated, and the data sent * to the frontend isn't either. * -------------------------------- */voidpq_sendcountedtext(StringInfo buf, const char *str, int slen,				   bool countincludesself){	int			extra = countincludesself ? 4 : 0;	char	   *p;	p = pg_server_to_client(str, slen);	if (p != str)				/* actual conversion has been done? */	{		slen = strlen(p);		pq_sendint(buf, slen + extra, 4);		appendBinaryStringInfo(buf, p, slen);		pfree(p);	}	else	{		pq_sendint(buf, slen + extra, 4);		appendBinaryStringInfo(buf, str, slen);	}}/* -------------------------------- *		pq_sendtext		- append a text string (with conversion) * * The passed text string need not be null-terminated, and the data sent * to the frontend isn't either.  Note that this is not actually useful * for direct frontend transmissions, since there'd be no way for the * frontend to determine the string length.  But it is useful for binary * format conversions. * -------------------------------- */voidpq_sendtext(StringInfo buf, const char *str, int slen){	char	   *p;	p = pg_server_to_client(str, slen);	if (p != str)				/* actual conversion has been done? */	{		slen = strlen(p);		appendBinaryStringInfo(buf, p, slen);		pfree(p);	}	else		appendBinaryStringInfo(buf, str, slen);}/* -------------------------------- *		pq_sendstring	- append a null-terminated text string (with conversion) * * NB: passed text string must be null-terminated, and so is the data * sent to the frontend. * -------------------------------- */voidpq_sendstring(StringInfo buf, const char *str){	int			slen = strlen(str);	char	   *p;	p = pg_server_to_client(str, slen);	if (p != str)				/* actual conversion has been done? */	{		slen = strlen(p);		appendBinaryStringInfo(buf, p, slen + 1);		pfree(p);	}	else		appendBinaryStringInfo(buf, str, slen + 1);}/* -------------------------------- *		pq_sendint		- append a binary integer to a StringInfo buffer * -------------------------------- */voidpq_sendint(StringInfo buf, int i, int b){	unsigned char n8;	uint16		n16;	uint32		n32;	switch (b)	{		case 1:			n8 = (unsigned char) i;			appendBinaryStringInfo(buf, (char *) &n8, 1);			break;		case 2:			n16 = htons((uint16) i);			appendBinaryStringInfo(buf, (char *) &n16, 2);			break;		case 4:			n32 = htonl((uint32) i);			appendBinaryStringInfo(buf, (char *) &n32, 4);			break;		default:			elog(ERROR, "unsupported integer size %d", b);			break;	}}/* -------------------------------- *		pq_sendint64	- append a binary 8-byte int to a StringInfo buffer * * It is tempting to merge this with pq_sendint, but we'd have to make the * argument int64 for all data widths --- that could be a big performance * hit on machines where int64 isn't efficient. * -------------------------------- */voidpq_sendint64(StringInfo buf, int64 i){	uint32		n32;	/* High order half first, since we're doing MSB-first */#ifdef INT64_IS_BUSTED	/* don't try a right shift of 32 on a 32-bit word */	n32 = (i < 0) ? -1 : 0;#else	n32 = (uint32) (i >> 32);#endif	n32 = htonl(n32);	appendBinaryStringInfo(buf, (char *) &n32, 4);	/* Now the low order half */	n32 = (uint32) i;	n32 = htonl(n32);	appendBinaryStringInfo(buf, (char *) &n32, 4);}/* -------------------------------- *		pq_sendfloat4	- append a float4 to a StringInfo buffer * * The point of this routine is to localize knowledge of the external binary * representation of float4, which is a component of several datatypes. * * We currently assume that float4 should be byte-swapped in the same way * as int4.  This rule is not perfect but it gives us portability across * most IEEE-float-using architectures. * -------------------------------- */voidpq_sendfloat4(StringInfo buf, float4 f){	union	{		float4		f;		uint32		i;	}			swap;	swap.f = f;	swap.i = htonl(swap.i);	appendBinaryStringInfo(buf, (char *) &swap.i, 4);}/* -------------------------------- *		pq_sendfloat8	- append a float8 to a StringInfo buffer * * The point of this routine is to localize knowledge of the external binary * representation of float8, which is a component of several datatypes. * * We currently assume that float8 should be byte-swapped in the same way * as int8.  This rule is not perfect but it gives us portability across * most IEEE-float-using architectures. * -------------------------------- */voidpq_sendfloat8(StringInfo buf, float8 f){#ifdef INT64_IS_BUSTED	union	{		float8		f;		uint32		h[2];	}			swap;	swap.f = f;	swap.h[0] = htonl(swap.h[0]);	swap.h[1] = htonl(swap.h[1]);	/* Have to figure out endianness by testing... */	if (((uint32) 1) == htonl((uint32) 1))	{		/* machine seems to be big-endian, send h[0] first */		appendBinaryStringInfo(buf, (char *) &swap.h[0], 4);		appendBinaryStringInfo(buf, (char *) &swap.h[1], 4);	}	else	{		/* machine seems to be little-endian, send h[1] first */		appendBinaryStringInfo(buf, (char *) &swap.h[1], 4);		appendBinaryStringInfo(buf, (char *) &swap.h[0], 4);	}#else	union	{		float8		f;		int64		i;	}			swap;	swap.f = f;	pq_sendint64(buf, swap.i);#endif}/* -------------------------------- *		pq_endmessage	- send the completed message to the frontend * * The data buffer is pfree()d, but if the StringInfo was allocated with * makeStringInfo then the caller must still pfree it. * --------------------------------

⌨️ 快捷键说明

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