Re: [HACKERS] patch: function xmltable

Поиск
Список
Период
Сортировка
От Alvaro Herrera
Тема Re: [HACKERS] patch: function xmltable
Дата
Msg-id 20170116233000.aooak7ytomrhvyjo@alvherre.pgsql
обсуждение исходный текст
Ответ на Re: [HACKERS] patch: function xmltable  (Alvaro Herrera <alvherre@2ndquadrant.com>)
Список pgsql-hackers
In case this still matters, I think GetValue should look more or less
like this (untested):


/** Return the value for column number 'colnum' for the current row.  If column* -1 is requested, return representation
ofthe whole row.** This leaks memory, so be sure to reset often the context in which it's* called.*/
 
static Datum
XmlTableGetValue(TableExprState *state, int colnum, bool *isnull)
{
#ifdef USE_LIBXMLXmlTableBuilderData *xtCxt;Datum        result = (Datum) 0;xmlNodePtr    cur;char       *cstr =
NULL;volatilexmlXPathObjectPtr xpathobj;
 
xtCxt = GetXmlTableBuilderPrivateData(state, "XmlTableGetValue");
Assert(xtCxt->xpathobj &&       xtCxt->xpathobj->type == XPATH_NODESET &&       xtCxt->xpathobj->nodesetval != NULL);
/* Propagate context related error context to libxml2 */xmlSetStructuredErrorFunc((void *) xtCxt->xmlerrcxt,
xml_errorHandler);
cur = xtCxt->xpathobj->nodesetval->nodeTab[xtCxt->row_count - 1];if (cur->type != XML_ELEMENT_NODE)    elog(ERROR,
"unexpectedxmlNode type");
 
/* Handle whole row case the easy way. */if (colnum == -1){    text       *txt;
    txt = xml_xmlnodetoxmltype(cur, xtCxt->xmlerrcxt);    result = InputFunctionCall(&state->in_functions[0],
                   text_to_cstring(txt),                               state->typioparams[0],
   -1);    *isnull = false;
 
    return result;}
Assert(xtCxt->xpathscomp[colnum] != NULL);
xpathobj = NULL;PG_TRY();{    Form_pg_attribute attr;
    attr = state->resultSlot->tts_tupleDescriptor->attrs[colnum];
    /* Set current node as entry point for XPath evaluation */    xmlXPathSetContextNode(cur, xtCxt->xpathcxt);
    /* Evaluate column path */    xpathobj = xmlXPathCompiledEval(xtCxt->xpathscomp[colnum], xtCxt->xpathcxt);    if
(xpathobj== NULL || xtCxt->xmlerrcxt->err_occurred)        xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
                  "could not create XPath object");
 
    if (xpathobj->type == XPATH_NODESET)    {        int            count;        Oid            targettypid =
attr->atttypid;
        if (xpathobj->nodesetval != NULL)            count = xpathobj->nodesetval->nodeNr;
        /*         * There are four possible cases, depending on the number of         * nodes returned by the XPath
expressionand the type of the         * target column: a) XPath returns no nodes.  b) One node is         * returned,
andcolumn is of type XML.  c) One node, column type         * other than XML.  d) Multiple nodes are returned.
*/       if (xpathobj->nodesetval == NULL)        {            *isnull = true;        }        else if (count == 1 &&
targettypid== XMLOID)        {            textstr = xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[0],
                            xtCxt->xmlerrcxt);            cstr = text_to_cstring(textstr);        }        else if
(count== 1)        {            xmlChar    *str;
 
            str = xmlNodeListGetString(xtCxt->doc,
xpathobj->nodesetval->nodeTab[0]->xmlChildrenNode,                                      1);            if (str)
  {                PG_TRY();                {                    cstr = pstrdup(str);                }
PG_CATCH();               {                    xmlFree(str);                    PG_RE_THROW();                }
      PG_END_TRY();                xmlFree(str);            }            else                cstr = pstrdup("");
}       else        {            StringInfoData buf;            int            i;
 
            Assert(count > 1);
            /*             * When evaluating the XPath expression returns multiple             * nodes, the result is
theconcatenation of them all.             * The target type must be XML.             */            if (targettypid !=
XMLOID)               ereport(ERROR,                        (errcode(ERRCODE_CARDINALITY_VIOLATION),
    errmsg("more than one value returned by column XPath expression")));
 
            initStringInfo(&buf);            for (i = 0; i < count; i++)                /* worth freeing the text here?
Naahh ... */                appendStringInfoText(&buf,
xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i],
xtCxt->xmlerrcxt));           cstr = buf.data;        }    }    else if (xpathobj->type == XPATH_STRING)    {
cstr= (char *) xpathobj->stringval;        *isnull = false;    }    else        elog(ERROR, "unexpected XPath object
type%u", xpathobj->type);
 
    /*     * By here, either cstr contains the result value, or the isnull flag     * has been set.     */
Assert(cstr|| *isnull);
 
    if (!*isnull)        result = InputFunctionCall(&state->in_functions[colnum],
cstr,                                  state->typioparams[colnum],
attr->atttypmod);}PG_CATCH();{   if (xpathobj != NULL)        xmlXPathFreeObject(xpathobj);
PG_RE_THROW();}PG_END_TRY();
if (xpathobj)    xmlXPathFreeObject(xpathobj);
return result;
#elseNO_XML_SUPPORT();
#endif   /* not USE_LIBXML */
}

-- 
Álvaro Herrera                https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



В списке pgsql-hackers по дате отправления:

Предыдущее
От: Alvaro Herrera
Дата:
Сообщение: Re: [HACKERS] patch: function xmltable
Следующее
От: David Rowley
Дата:
Сообщение: Re: [HACKERS] PoC: Grouped base relation