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

📄 xml.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		pfree(elem_values);		pfree(elem_nulls);	}	else	{		Oid			typeOut;		bool		isvarlena;		char	   *p,				   *str;		/*		 * Special XSD formatting for some data types		 */		switch (type)		{			case BOOLOID:				if (DatumGetBool(value))					return "true";				else					return "false";			case DATEOID:				{					DateADT		date;					struct pg_tm tm;					char		buf[MAXDATELEN + 1];					date = DatumGetDateADT(value);					j2date(date + POSTGRES_EPOCH_JDATE,						   &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));					EncodeDateOnly(&tm, USE_XSD_DATES, buf);					return pstrdup(buf);				}			case TIMESTAMPOID:				{					Timestamp	timestamp;					struct pg_tm tm;					fsec_t		fsec;					char	   *tzn = NULL;					char		buf[MAXDATELEN + 1];					timestamp = DatumGetTimestamp(value);					/* XSD doesn't support infinite values */					if (TIMESTAMP_NOT_FINITE(timestamp))						ereport(ERROR,								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),								 errmsg("timestamp out of range")));					else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)						EncodeDateTime(&tm, fsec, NULL, &tzn, USE_XSD_DATES, buf);					else						ereport(ERROR,								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),								 errmsg("timestamp out of range")));					return pstrdup(buf);				}			case TIMESTAMPTZOID:				{					TimestampTz timestamp;					struct pg_tm tm;					int			tz;					fsec_t		fsec;					char	   *tzn = NULL;					char		buf[MAXDATELEN + 1];					timestamp = DatumGetTimestamp(value);					/* XSD doesn't support infinite values */					if (TIMESTAMP_NOT_FINITE(timestamp))						ereport(ERROR,								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),								 errmsg("timestamp out of range")));					else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)						EncodeDateTime(&tm, fsec, &tz, &tzn, USE_XSD_DATES, buf);					else						ereport(ERROR,								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),								 errmsg("timestamp out of range")));					return pstrdup(buf);				}		}		getTypeOutputInfo(type, &typeOut, &isvarlena);		str = OidOutputFunctionCall(typeOut, value);		if (type == XMLOID)			return str;#ifdef USE_LIBXML		if (type == BYTEAOID)		{			xmlBufferPtr buf;			xmlTextWriterPtr writer;			char	   *result;			xml_init();			buf = xmlBufferCreate();			writer = xmlNewTextWriterMemory(buf, 0);			if (xmlbinary == XMLBINARY_BASE64)				xmlTextWriterWriteBase64(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);			else				xmlTextWriterWriteBinHex(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);			xmlFreeTextWriter(writer);			result = pstrdup((const char *) xmlBufferContent(buf));			xmlBufferFree(buf);			return result;		}#endif   /* USE_LIBXML */		for (p = str; *p; p += pg_mblen(p))		{			switch (*p)			{				case '&':					appendStringInfo(&buf, "&amp;");					break;				case '<':					appendStringInfo(&buf, "&lt;");					break;				case '>':					appendStringInfo(&buf, "&gt;");					break;				case '\r':					appendStringInfo(&buf, "&#x0d;");					break;				default:					appendBinaryStringInfo(&buf, p, pg_mblen(p));					break;			}		}	}	return buf.data;}static char *_SPI_strdup(const char *s){	size_t		len = strlen(s) + 1;	char	   *ret = SPI_palloc(len);	memcpy(ret, s, len);	return ret;}/* * SQL to XML mapping functions * * What follows below is intentionally organized so that you can read * along in the SQL/XML:2003 standard.	The functions are mostly split * up and ordered they way the clauses lay out in the standards * document, and the identifiers are also aligned with the standard * text.  (SQL/XML:2006 appears to be ordered differently, * unfortunately.) * * There are many things going on there: * * There are two kinds of mappings: Mapping SQL data (table contents) * to XML documents, and mapping SQL structure (the "schema") to XML * Schema.	And there are functions that do both at the same time. * * Then you can map a database, a schema, or a table, each in both * ways.  This breaks down recursively: Mapping a database invokes * mapping schemas, which invokes mapping tables, which invokes * mapping rows, which invokes mapping columns, although you can't * call the last two from the outside.	Because of this, there are a * number of xyz_internal() functions which are to be called both from * the function manager wrapper and from some upper layer in a * recursive call. * * See the documentation about what the common function arguments * nulls, tableforest, and targetns mean. * * Some style guidelines for XML output: Use double quotes for quoting * XML attributes.	Indent XML elements by two spaces, but remember * that a lot of code is called recursively at different levels, so * it's better not to indent rather than create output that indents * and outdents weirdly.  Add newlines to make the output look nice. *//* * Visibility of objects for XML mappings; see SQL/XML:2003 section * 4.8.5. *//* * Given a query, which must return type oid as first column, produce * a list of Oids with the query results. */static List *query_to_oid_list(const char *query){	int			i;	List	   *list = NIL;	SPI_execute(query, true, 0);	for (i = 0; i < SPI_processed; i++)	{		Datum		oid;		bool		isnull;		oid = SPI_getbinval(SPI_tuptable->vals[i],							SPI_tuptable->tupdesc,							1,							&isnull);		if (!isnull)			list = lappend_oid(list, DatumGetObjectId(oid));	}	return list;}static List *schema_get_xml_visible_tables(Oid nspid){	StringInfoData query;	initStringInfo(&query);	appendStringInfo(&query, "SELECT oid FROM pg_catalog.pg_class WHERE relnamespace = %u AND relkind IN ('r', 'v') AND pg_catalog.has_table_privilege (oid, 'SELECT') ORDER BY relname;", nspid);	return query_to_oid_list(query.data);}/* * Including the system schemas is probably not useful for a database * mapping. */#define XML_VISIBLE_SCHEMAS_EXCLUDE "(nspname ~ '^pg_' OR nspname = 'information_schema')"#define XML_VISIBLE_SCHEMAS "SELECT oid FROM pg_catalog.pg_namespace WHERE pg_catalog.has_schema_privilege (oid, 'USAGE') AND NOT " XML_VISIBLE_SCHEMAS_EXCLUDEstatic List *database_get_xml_visible_schemas(void){	return query_to_oid_list(XML_VISIBLE_SCHEMAS " ORDER BY nspname;");}static List *database_get_xml_visible_tables(void){	/* At the moment there is no order required here. */	return query_to_oid_list("SELECT oid FROM pg_catalog.pg_class WHERE relkind IN ('r', 'v') AND pg_catalog.has_table_privilege (pg_class.oid, 'SELECT') AND relnamespace IN (" XML_VISIBLE_SCHEMAS ");");}/* * Map SQL table to XML and/or XML Schema document; see SQL/XML:2003 * section 9.3. */static StringInfotable_to_xml_internal(Oid relid,					  const char *xmlschema, bool nulls, bool tableforest,					  const char *targetns, bool top_level){	StringInfoData query;	initStringInfo(&query);	appendStringInfo(&query, "SELECT * FROM %s",					 DatumGetCString(DirectFunctionCall1(regclassout,												  ObjectIdGetDatum(relid))));	return query_to_xml_internal(query.data, get_rel_name(relid),								 xmlschema, nulls, tableforest,								 targetns, top_level);}Datumtable_to_xml(PG_FUNCTION_ARGS){	Oid			relid = PG_GETARG_OID(0);	bool		nulls = PG_GETARG_BOOL(1);	bool		tableforest = PG_GETARG_BOOL(2);	const char *targetns = _textout(PG_GETARG_TEXT_P(3));	PG_RETURN_XML_P(stringinfo_to_xmltype(table_to_xml_internal(relid, NULL,														  nulls, tableforest,														   targetns, true)));}Datumquery_to_xml(PG_FUNCTION_ARGS){	char	   *query = _textout(PG_GETARG_TEXT_P(0));	bool		nulls = PG_GETARG_BOOL(1);	bool		tableforest = PG_GETARG_BOOL(2);	const char *targetns = _textout(PG_GETARG_TEXT_P(3));	PG_RETURN_XML_P(stringinfo_to_xmltype(query_to_xml_internal(query, NULL,													NULL, nulls, tableforest,														   targetns, true)));}Datumcursor_to_xml(PG_FUNCTION_ARGS){	char	   *name = _textout(PG_GETARG_TEXT_P(0));	int32		count = PG_GETARG_INT32(1);	bool		nulls = PG_GETARG_BOOL(2);	bool		tableforest = PG_GETARG_BOOL(3);	const char *targetns = _textout(PG_GETARG_TEXT_P(4));	StringInfoData result;	Portal		portal;	int			i;	initStringInfo(&result);	SPI_connect();	portal = SPI_cursor_find(name);	if (portal == NULL)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_CURSOR),				 errmsg("cursor \"%s\" does not exist", name)));	SPI_cursor_fetch(portal, true, count);	for (i = 0; i < SPI_processed; i++)		SPI_sql_row_to_xmlelement(i, &result, NULL, nulls,								  tableforest, targetns, true);	SPI_finish();	PG_RETURN_XML_P(stringinfo_to_xmltype(&result));}/* * Write the start tag of the root element of a data mapping. * * top_level means that this is the very top level of the eventual * output.	For example, when the user calls table_to_xml, then a call * with a table name to this function is the top level.  When the user * calls database_to_xml, then a call with a schema name to this * function is not the top level.  If top_level is false, then the XML * namespace declarations are omitted, because they supposedly already * appeared earlier in the output.	Repeating them is not wrong, but * it looks ugly. */static voidxmldata_root_element_start(StringInfo result, const char *eltname,						   const char *xmlschema, const char *targetns,						   bool top_level){	/* This isn't really wrong but currently makes no sense. */	Assert(top_level || !xmlschema);	appendStringInfo(result, "<%s", eltname);	if (top_level)	{		appendStringInfoString(result, " xmlns:xsi=\"" NAMESPACE_XSI "\"");		if (strlen(targetns) > 0)			appendStringInfo(result, " xmlns=\"%s\"", targetns);	}	if (xmlschema)	{		/* FIXME: better targets */		if (strlen(targetns) > 0)			appendStringInfo(result, " xsi:schemaLocation=\"%s #\"", targetns);		else			appendStringInfo(result, " xsi:noNamespaceSchemaLocation=\"#\"");	}	appendStringInfo(result, ">\n\n");}static voidxmldata_root_element_end(StringInfo result, const char *eltname){	appendStringInfo(result, "</%s>\n", eltname);}static StringInfoquery_to_xml_internal(const char *query, char *tablename,					  const char *xmlschema, bool nulls, bool tableforest,					  const char *targetns, bool top_level){	StringInfo	result;	char	   *xmltn;	int			i;	if (tablename)		xmltn = map_sql_identifier_to_xml_name(tablename, true, false);	else		xmltn = "table";	result = makeStringInfo();	SPI_connect();	if (SPI_execute(query, true, 0) != SPI_OK_SELECT)		ereport(ERROR,				(errcode(ERRCODE_DATA_EXCEPTION),				 errmsg("invalid query")));	if (!tableforest)		xmldata_root_element_start(result, xmltn, xmlschema,								   targetns, top_level);	if (xmlschema)		appendStringInfo(result, "%s\n\n", xmlschema);	for (i = 0; i < SPI_processed; i++)		SPI_sql_row_to_xmlelement(i, result, tablename, nulls,								  tableforest, targetns, top_level);	if (!tableforest)		xmldata_root_element_end(result, xmltn);	SPI_finish();	return result;}Datumtable_to_xmlschema(PG_FUNCTION_ARGS){	Oid			relid = PG_GETARG_OID(0);	bool		nulls = PG_GETARG_BOOL(1);	bool		tableforest = PG_GETARG_BOOL(2);	const char *targetns = _textout(PG_GETARG_TEXT_P(3));	const char *result;	Relation	rel;	rel = heap_open(relid, AccessShareLock);	result = map_sql_table_to_xmlschema(rel->rd_att, relid, nulls,										tableforest, targetns);	heap_close(rel, NoLock);	PG_RETURN_XML_P(cstring_to_xmltype(result));}Datumquery_to_xmlschema(PG_FUNCTION_ARGS){	char	   *query = _textout(PG_GETARG_TEXT_P(0));	bool		nulls = PG_GETARG_BOOL(1);	bool		tableforest = PG_GETARG_BOOL(2);	const char *targetns = _textout(PG_GETARG_TEXT_P(3));	const char *result;	SPIPlanPtr	plan;	Portal		portal;	SPI_connect();	if ((plan = SPI_prepare(query, 0, NULL)) == NULL)		elog(ERROR, "SPI_prepare(\"%s\") failed", query);	if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL, true)) == NULL)		elog(ERROR, "SPI_cursor_open(\"%s\") failed", query);	result = _SPI_strdup(map_sql_table_to_xmlschema(portal->tupDesc,													InvalidOid, nulls,													tableforest, targetns));	SPI_cursor_close(portal);	SPI_finish();	PG_RETURN_XML_P(cstring_to_xmltype(result));}Datumcursor_to_xmlschema(PG_FUNCTION_ARGS){	char	   *name = _textout(PG_GETARG_TEXT_P(0));	bool		nulls = PG_GETARG_BOOL(1);	bool		tableforest = PG_GETARG_BOOL(2);	const char *targetns = _textout(PG_GETARG_TEXT_P(3));	const char *xmlschema;	Portal		portal;	SPI_connect();	portal = SPI_cursor_find(name);	if (portal == NULL)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_CURSOR),				 errmsg("cursor \"%s\" does not exist", name)));	xmlschema = _SPI_strdup(map_sql_table_to_xmlschema(portal->tupDesc,													   InvalidOid, nulls,													 tableforest, targetns));	SPI_finish();	PG_RETURN_XML_P(cstring_to_xmltype(xmlschema));}Datumtable_to_xml_and_xmlschema(PG_FUNCTION_ARGS){	Oid			relid = PG_GETARG_OID(0);	bool		nulls = PG_GETARG_BOOL(1);	bool		tableforest = PG_GETARG_BOOL(2);	const char *targetns = _textout(PG_GETARG_TEXT_P(3));	Relation	rel;	const char *xmlschema;	rel = heap_open(relid, AccessShareLock);	xmlschema = map_sql_table_to_xmlschema(rel->rd_att, relid, nulls,										   tableforest, targetns);	heap_close(rel, NoLock);	PG_RETURN_XML_P(stringinfo_to_xmltype(table_to_xml_internal(relid,											   xmlschema, nulls, tableforest,														   targetns, true)));}Datumquery_to_xml_and_xmlschema(PG_FUNCTION_ARGS){	char	   *query = _textout(PG_GETARG_TEXT_P(0));	bool		nulls = PG_GETARG_BOOL(1);	bool		tableforest = PG_GETARG_BOOL(2);	const char *targetns = _textout(PG_GETARG_TEXT_P(3));	const char *xmlschema;	SPIPlanPtr	plan;	Portal		portal;	SPI_connect();	if ((plan = SPI_prepare(query, 0, NULL)) == NULL)		elog(ERROR, "SPI_prepare(\"%s\") failed", query);	if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL, true)) == NULL)		elog(ERROR, "SPI_cursor_open(\"%s\") failed", query);

⌨️ 快捷键说明

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