Example #1
0
/*
 * Entry point for native XML support, shred XML document into tables and
 * create indexes for future XQuery support
 * @param
 * @return
 */
Datum
build_xmlindex(PG_FUNCTION_ARGS)
{
    xmltype     *xmldata    = NULL;
    char        *xmldataint = NULL;
	text		*xml_name	= NULL;
	char		*xml_nameint;
	int			xmldatalen	= -1;
	int			loader_return = 0;	// false
	int4		did;


#ifdef USE_LIBXML
	elog(INFO, "build_xmlindex started");

	xmldata     = PG_GETARG_XML_P(0);
    xmldataint  = VARDATA(xmldata);
	xmldatalen  = VARSIZE(xmldata) - VARHDRSZ;
	xmldataint[xmldatalen] = 0;

	xml_name	= PG_GETARG_TEXT_P(1);
	xml_nameint	= VARDATA(xml_name);
	xml_nameint[VARSIZE(xml_name) - VARHDRSZ] = 0;
	
	//initialize LibXML structures, if allready done -> do nothing
    pg_xml_init();
	xmlInitParser();


	did = insert_xmldata_into_table(xmldataint, xml_nameint);

	loader_return = xml_index_entry(xmldataint, xmldatalen, did);
	
	elog(INFO, "build_xmlindex ended");
	if (loader_return == XML_INDEX_LOADER_SUCCES)
	{
		PG_RETURN_BOOL(true);
	} else
	{
		PG_RETURN_BOOL(false);
	}
#else
    NO_XML_SUPPORT();
    PG_RETURN_BOOL (false);
#endif
}
Example #2
0
/**
 * Validation function take first argument as XML type, then check if is
 * well formated. If so, do the same for DTD document. If both success, check
 * XML document against DTD schema restrictions.
 * @return true if pass, false otherwise
 */
Datum xmlvalidate_dtd(PG_FUNCTION_ARGS)
{
#ifdef USE_LIBXML
	int ret = -1;
	xmlValidCtxtPtr validctxt   = NULL;
	xmlDtdPtr       dtd         = NULL;
    bool			result		= false;
    text			*data		= NULL;
	char			*dtdstr		= NULL;
    xmltype			*xmldata	= NULL;
    char			*xmldataint = NULL;
    xmlChar			*xmldatastr = NULL;
    int				lenxml  = -1;       // length of xml data
    xmlDocPtr               doc = NULL;

	 // creating xmlChar * from internal xmltype of stored XML
    xmldata     = PG_GETARG_XML_P(0);
    xmldataint  = VARDATA(xmldata);
    lenxml      = VARSIZE(xmldata) - VARHDRSZ;
    xmldatastr  = (xmlChar *) palloc((lenxml + 1) * sizeof(xmlChar));
	memcpy(xmldatastr, xmldataint, lenxml);
	xmldatastr[lenxml] = '\0';

    // creating xmlChar* from text representation of DTD
    data = PG_GETARG_TEXT_P(1);
	dtdstr = text_to_cstring(data);

    //initialize LibXML structures, if allready done -> do nothing
    pg_xml_init();
	xmlInitParser();

    doc = xmlReadMemory((const char *)xmldatastr, lenxml, "include.xml", NULL, 0);

     if (doc == NULL) {
        elog(ERROR, "Failed to parse XML document");
        PG_RETURN_BOOL (false);
    }

	// create DTD from memory, must use XML_CHAR_ENCODING_NONE 
	dtd = xmlIOParseDTD(NULL,
				xmlParserInputBufferCreateMem(dtdstr, strlen(dtdstr),
						 XML_CHAR_ENCODING_NONE),
				XML_CHAR_ENCODING_NONE);

    if (dtd == NULL)
    { // unable to create parser context
        elog(ERROR, "Error with creating DTD schema, check if schema is valid");
        PG_RETURN_BOOL (false);
    }

	validctxt = xmlNewValidCtxt();
	if (validctxt == NULL)
	{ // cant create validation context
		elog(INFO ,"cant create validation context");
		xmlFreeDtd(dtd);
		PG_RETURN_BOOL (false);
	}

	ret = xmlValidateDtd(validctxt, doc, dtd);
	if (ret == 0)
    {
        elog(INFO, "Validates");
        result = true;
    } else if (ret > 0)
    {
        elog(INFO, "Dont validates");
        result = false;
    } else
    {
        elog(INFO, "Validation generated an internal error");
        result = false;
    }

	xmlFreeDtd(dtd);
	xmlFreeValidCtxt(validctxt);

	xmlFreeDoc(doc);    // clean up document in memmory
    xmlCleanupParser(); // clean up stream parser
	PG_RETURN_BOOL (result);
#else
    NO_XML_SUPPORT();
    PG_RETURN_BOOL (false);
#endif
	}
Example #3
0
/**
 * Validation function take first argument as XML type, then check if is
 * well formated. If so, do the same for RNG document. If both success, check
 * XML document against RNG schema restrictions.
 * @return true if pass, false otherwise
 */
Datum
xmlvalidate_rng(PG_FUNCTION_ARGS)
{
#ifdef USE_LIBXML

    text        *data   = NULL;
	char        *rng    = NULL;
	xmlChar     *utf8rng    = NULL;
    xmltype     *xmldata    = NULL;
    char        *xmldataint = NULL;
    xmlChar     *xmldatastr = NULL;
    bool        result  = false;
    int         lenxml  = -1;       // length of xml data
    int         lenrng  = -1;       // length of xsd data
    xmlDocPtr               doc = NULL;
    int ret = -1;

    xmlRelaxNGParserCtxtPtr ctxt    = NULL;
    xmlRelaxNGPtr           schema  = NULL;
    xmlRelaxNGValidCtxtPtr   validctxt = NULL;


    // creating xmlChar * from internal xmltype of stored XML
    xmldata     = PG_GETARG_XML_P(0);
    xmldataint  = VARDATA(xmldata);
    lenxml      = VARSIZE(xmldata) - VARHDRSZ;
    xmldatastr  = (xmlChar *) palloc((lenxml + 1) * sizeof(xmlChar));
	memcpy(xmldatastr, xmldataint, lenxml);
	xmldatastr[lenxml] = '\0';

    // creating xmlChar* from text representation of XSD
    data = PG_GETARG_TEXT_P(1);
	lenrng = VARSIZE(data) - VARHDRSZ;
	rng = text_to_cstring(data);

    //encode XML to internal representation with UTF-8, only one used in LibXML
	utf8rng = pg_do_encoding_conversion((unsigned char*)rng,
										   lenrng,
										   GetDatabaseEncoding(),
										   PG_UTF8);

    //initialize LibXML structures, if allready done -> do nothing
    pg_xml_init();
	xmlInitParser();

    doc = xmlReadMemory((const char *)xmldatastr, lenxml, "include.xml", NULL, 0);

     if (doc == NULL) {
        elog(ERROR, "Failed to parse XML document");
        PG_RETURN_BOOL (false);
    }

    ctxt = xmlRelaxNGNewMemParserCtxt(rng, lenrng);

    if (ctxt == NULL)
    { // unable to create parser context
        elog(ERROR, "Error with creating schema, check if RelaxNG schema is valid");
        PG_RETURN_BOOL (false);
    }

    schema = xmlRelaxNGParse(ctxt);  // parse schema
    xmlRelaxNGFreeParserCtxt(ctxt);  // realease parser context

    validctxt = xmlRelaxNGNewValidCtxt(schema);
    if (validctxt == NULL)
    { // cant create validation context
        xmlRelaxNGFree(schema);
        elog(ERROR, "Cant create validation context");
        PG_RETURN_BOOL (false);
    }

    // set errors to SQL errors
	xmlRelaxNGSetValidErrors(validctxt,
			    xml_error_handler,
			    NULL,
			    0);

    ret = xmlRelaxNGValidateDoc(validctxt, doc);
    if (ret == 0)
    {
        elog(INFO, "Validates");
        result = true;
    } else if (ret > 0)
    {
        elog(INFO, "Dont validates");
        result = false;
    } else
    {
        elog(INFO, "Validation generated an internal error");
        result = false;
    }

    xmlRelaxNGFree(schema);
    xmlRelaxNGFreeValidCtxt(validctxt);

    xmlFreeDoc(doc);    // clean up document in memmory
    xmlCleanupParser(); // clean up stream parser

	PG_RETURN_BOOL (result);
#else
    NO_XML_SUPPORT();
    PG_RETURN_BOOL (false);
#endif
}
Example #4
0
/*
 * Internal handler function
 */
static Datum
handler_internal(Oid function_oid, FunctionCallInfo fcinfo, bool execute)
{
	HeapTuple	proctuple;
	Form_pg_proc pg_proc_entry;
	char	   *sourcecode;
	Datum		prosrcdatum;
	bool		isnull;
	const char **xslt_params;
	int			i;
	Oid		   *argtypes;
	char	  **argnames;
	char	   *argmodes;
	int			numargs;
	xmlDocPtr	ssdoc;
	xmlDocPtr	xmldoc;
	xmlDocPtr	resdoc;
	xsltStylesheetPtr stylesheet;
	int			reslen;
	xmlChar	   *resstr;
	Datum		resdatum;

	if (CALLED_AS_TRIGGER(fcinfo))
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("trigger functions not supported")));

	proctuple = SearchSysCache(PROCOID, ObjectIdGetDatum(function_oid), 0, 0, 0);
	if (!HeapTupleIsValid(proctuple))
		elog(ERROR, "cache lookup failed for function %u", function_oid);

	prosrcdatum = SysCacheGetAttr(PROCOID, proctuple, Anum_pg_proc_prosrc, &isnull);
	if (isnull)
		elog(ERROR, "null prosrc");

	sourcecode = pstrdup(DatumGetCString(DirectFunctionCall1(textout,
															 prosrcdatum)));
	/* allow one blank line at the start */
	if (sourcecode[0] == '\n')
		sourcecode++;

	numargs = get_func_arg_info(proctuple,
								&argtypes, &argnames, &argmodes);

	if (numargs < 1)
		ereport(ERROR,
				(errmsg("XSLT function must have at least one argument")));

				if (argtypes[0] != XMLOID)
		ereport(ERROR,
				(errmsg("first argument of XSLT function must have type XML")));

#if 0
	xsltSetGenericErrorFunc(NULL, xmlGenericError);
#endif

	ssdoc = xmlParseDoc((xmlChar *) sourcecode); /* XXX use backend's xml_parse here() */
	stylesheet = xsltParseStylesheetDoc(ssdoc); /* XXX check error handling */
	if (!stylesheet)
		ereport(ERROR,
				(errmsg("could not parse stylesheet")));

	pg_proc_entry = (Form_pg_proc) GETSTRUCT(proctuple);

	{
		char	   *method;

		method = (char *) stylesheet->method;
		/*
		 * TODO: This is strictly speaking not correct because the
		 * default output method may be "html", but that can only
		 * detected at run time, so punt for now.
		 */
		if (!method)
			method = "xml";

		if (strcmp(method, "xml") == 0 && pg_proc_entry->prorettype != XMLOID)
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("XSLT stylesheet has output method \"xml\" but return type of function is not xml")));
		else if ((strcmp(method, "html") == 0 || strcmp(method, "text") == 0)
				 && pg_proc_entry->prorettype != TEXTOID && pg_proc_entry->prorettype != VARCHAROID)
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("XSLT stylesheet has output method \"%s\" but return type of function is not text or varchar", method)));
	}

	/* validation stops here */
	if (!execute)
	{
		ReleaseSysCache(proctuple);
		PG_RETURN_VOID();
	}

	/* execution begins here */

	xslt_params = palloc(((numargs - 1) * 2 + 1) * sizeof(*xslt_params));
	for (i = 0; i < numargs-1; i++)
	{
		xslt_params[i*2] = argnames[i+1];
		xslt_params[i*2+1] = type_to_cstring(PG_GETARG_DATUM(i+1),
											 argtypes[i+1]);
	}
	xslt_params[i*2] = NULL;

	{
		xmltype *arg0 = PG_GETARG_XML_P(0);
		// XXX this ought to use xml_parse()
		xmldoc = xmlParseMemory((char *) VARDATA(arg0), VARSIZE(arg0) - VARHDRSZ);
	}

	resdoc = xsltApplyStylesheet(stylesheet, xmldoc, xslt_params);
	if (!resdoc)
		elog(ERROR, "xsltApplyStylesheet() failed");

	xmlFreeDoc(xmldoc);

	if (xsltSaveResultToString(&resstr, &reslen, resdoc, stylesheet) != 0)
		elog(ERROR, "result serialization failed");

	xsltFreeStylesheet(stylesheet);
	xmlFreeDoc(resdoc);

	xsltCleanupGlobals();
	xmlCleanupParser();

	resdatum = cstring_to_type(resstr ? (char *) resstr : "", pg_proc_entry->prorettype);
	ReleaseSysCache(proctuple);
	PG_RETURN_DATUM(resdatum);
}