xpath improvement suggestion
От | Arie Bikker |
---|---|
Тема | xpath improvement suggestion |
Дата | |
Msg-id | 4B43C6AC.4020802@abikker.nl обсуждение исходный текст |
Ответы |
Re: xpath improvement suggestion
(Scott Bailey <artacus@comcast.net>)
Re: xpath improvement suggestion (Robert Haas <robertmhaas@gmail.com>) |
Список | pgsql-hackers |
Hi all, Well I had to burn some midnight oil trying to figure out why a construct like SELECT xpath('name()','<a/>'); doesn't give the expected result. Kept getting an empty array: xpath ------------- {} instead of the expected "{a}" BugID 4294 and the TODO item "better handling of XPath data types" pointed in the right direction. whithin src/backend/utils/adt/xml.c in the function xpath the result of the call to xmlXPathCompiledEval is not handled optimally. In fact, the result is assumed to be a nodeset without consulting the ->type member of the result. I've made some minor changes to xml.c to handle some non-nodeset results of xmlXPathCompiledEval. Essentially, the revised code makes an array of all the nodes in the xpathobj result in case this is a nodeset, or an array with a single element in case the reult is a number/string/boolean. The problem cases mentioned in http://archives.postgresql.org/pgsql-hackers/2008-06/msg00616.php now work as expected. Revision of the code involves: - A switch statement to handle the result type of xmlXPathCompiledEval. - an additional function xmlpathobjtoxmltype. diff of the revisioned code with respect to original is in attached file. kind regards, Arie Bikker 114d113 < static text *xml_xmlpathobjtoxmltype(xmlXPathObjectPtr cur); 3269,3309d3267 < < /* < * Convert XML pathobject to text for non-nodeset objects < */ < static text * < xml_xmlpathobjtoxmltype(xmlXPathObjectPtr cur) < { < xmltype *result; < < if (cur->type == XPATH_BOOLEAN) < { < PG_TRY(); < { < result = cstring_to_text((char *)(xmlXPathCastToBoolean(cur)?"t":"f")); < } < PG_CATCH(); < { < PG_RE_THROW(); < } < PG_END_TRY(); < } < else < { < xmlChar *str; < < str = xmlXPathCastToString(cur); < PG_TRY(); < { < result = (xmltype *) cstring_to_text((char *) str); < } < PG_CATCH(); < { < xmlFree(str); < PG_RE_THROW(); < } < PG_END_TRY(); < xmlFree(str); < } < < return result; < } 3463,3471c3421,3429 < switch (xpathobj->type) { < case XPATH_NODESET: { < /* return empty array in cases when nothing is found */ < if (xpathobj->nodesetval == NULL) < res_nitems = 0; < else < res_nitems = xpathobj->nodesetval->nodeNr; < < if (res_nitems) --- > /* return empty array in cases when nothing is found */ > if (xpathobj->nodesetval == NULL) > res_nitems = 0; > else > res_nitems = xpathobj->nodesetval->nodeNr; > > if (res_nitems) > { > for (i = 0; i < xpathobj->nodesetval->nodeNr; i++) 3473,3482c3431,3437 < for (i = 0; i < xpathobj->nodesetval->nodeNr; i++) < { < Datum elem; < bool elemisnull = false; < < elem = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i])); < astate = accumArrayResult(astate, elem, < elemisnull, XMLOID, < CurrentMemoryContext); < } --- > Datum elem; > bool elemisnull = false; > > elem = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i])); > astate = accumArrayResult(astate, elem, > elemisnull, XMLOID, > CurrentMemoryContext); 3484d3438 < break; 3486,3500d3439 < case XPATH_BOOLEAN: < case XPATH_NUMBER: < case XPATH_STRING: { < Datum elem; < bool elemisnull = false; < < elem = PointerGetDatum(xml_xmlpathobjtoxmltype(xpathobj)); < astate = accumArrayResult(astate, elem, < elemisnull, XMLOID, < CurrentMemoryContext); < break; < } < default: { < } < } 3524c3463 < if (astate== NULL) --- > if (res_nitems == 0)
В списке pgsql-hackers по дате отправления: