Пример #1
0
Datum
lt_q_regex(PG_FUNCTION_ARGS)
{
	ltree	   *tree = PG_GETARG_LTREE(0);
	ArrayType  *_query = PG_GETARG_ARRAYTYPE_P(1);
	lquery	   *query = (lquery *) ARR_DATA_PTR(_query);
	bool		res = false;
	int			num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));

	if (ARR_NDIM(_query) != 1)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("array must be one-dimensional")));

	while (num > 0)
	{
		if (DatumGetBool(DirectFunctionCall2(ltq_regex,
						 PointerGetDatum(tree), PointerGetDatum(query))))
		{

			res = true;
			break;
		}
		num--;
		query = NEXTVAL(query);
	}

	PG_FREE_IF_COPY(tree, 0);
	PG_FREE_IF_COPY(_query, 1);
	PG_RETURN_BOOL(res);
}
Пример #2
0
static bool
array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
{
	int			num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
	ltree	   *item = (ltree *) ARR_DATA_PTR(la);

	if (ARR_NDIM(la) > 1)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("array must be one-dimensional")));
	if (ARR_HASNULL(la))
		ereport(ERROR,
				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
				 errmsg("array must not contain nulls")));

	if (found)
		*found = NULL;
	while (num > 0)
	{
		if (DatumGetBool(DirectFunctionCall2(callback,
							 PointerGetDatum(item), PointerGetDatum(param))))
		{

			if (found)
				*found = item;
			return true;
		}
		num--;
		item = NEXTVAL(item);
	}

	return false;
}
Пример #3
0
Datum
_lca(PG_FUNCTION_ARGS)
{
	ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
	int			num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
	ltree	   *item = (ltree *) ARR_DATA_PTR(la);
	ltree	  **a,
			   *res;

	if (ARR_NDIM(la) > 1)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("array must be one-dimensional")));
	if (ARR_HASNULL(la))
		ereport(ERROR,
				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
				 errmsg("array must not contain nulls")));

	a = (ltree **) palloc(sizeof(ltree *) * num);
	while (num > 0)
	{
		num--;
		a[num] = item;
		item = NEXTVAL(item);
	}
	res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
	pfree(a);

	PG_FREE_IF_COPY(la, 0);

	if (res)
		PG_RETURN_POINTER(res);
	else
		PG_RETURN_NULL();
}
Пример #4
0
Datum
_lt_q_regex(PG_FUNCTION_ARGS)
{
	ArrayType  *_tree = PG_GETARG_ARRAYTYPE_P(0);
	ArrayType  *_query = PG_GETARG_ARRAYTYPE_P(1);
	lquery	   *query = (lquery *) ARR_DATA_PTR(_query);
	bool		res = false;
	int			num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));

	if (ARR_NDIM(_query) > 1)
		ereport(ERROR,
				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
				 errmsg("array must be one-dimensional")));
	if (ARR_HASNULL(_query))
		ereport(ERROR,
				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
				 errmsg("array must not contain nulls")));

	while (num > 0)
	{
		if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
		{
			res = true;
			break;
		}
		num--;
		query = (lquery *) NEXTVAL(query);
	}

	PG_FREE_IF_COPY(_tree, 0);
	PG_FREE_IF_COPY(_query, 1);
	PG_RETURN_BOOL(res);
}
Пример #5
0
Datum
_ltree_compress(PG_FUNCTION_ARGS)
{
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
	GISTENTRY  *retval = entry;

	if (entry->leafkey)
	{							/* ltree */
		ltree_gist *key;
		ArrayType  *val = DatumGetArrayTypeP(entry->key);
		int4		len = LTG_HDRSIZE + ASIGLEN;
		int			num = ArrayGetNItems(ARR_NDIM(val), ARR_DIMS(val));
		ltree	   *item = (ltree *) ARR_DATA_PTR(val);

		if (ARR_NDIM(val) != 1)
			ereport(ERROR,
					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
					 errmsg("array must be one-dimensional")));

		key = (ltree_gist *) palloc(len);
		key->len = len;
		key->flag = 0;

		MemSet(LTG_SIGN(key), 0, ASIGLEN);
		while (num > 0)
		{
			hashing(LTG_SIGN(key), item);
			num--;
			item = NEXTVAL(item);
		}

		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
		gistentryinit(*retval, PointerGetDatum(key),
					  entry->rel, entry->page,
					  entry->offset, key->len, FALSE);
	}
	else if (!LTG_ISALLTRUE(entry->key))
	{
		int4		i,
					len;
		ltree_gist *key;

		BITVECP		sign = LTG_SIGN(DatumGetPointer(entry->key));

		ALOOPBYTE(
				  if ((sign[i] & 0xff) != 0xff)
				  PG_RETURN_POINTER(retval);
		);
Пример #6
0
_X_EXPORT int
dixChangeGC(ClientPtr client, register GC *pGC, register BITS32 mask, CARD32 *pC32, ChangeGCValPtr pUnion)
{
    register BITS32 	index2;
    register int 	error = 0;
    PixmapPtr 		pPixmap;
    BITS32		maskQ;

    assert( (pC32 && !pUnion) || (!pC32 && pUnion) );
    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;

    maskQ = mask;	/* save these for when we walk the GCque */
    while (mask && !error) 
    {
	index2 = (BITS32) lowbit (mask);
	mask &= ~index2;
	pGC->stateChanges |= index2;
	switch (index2)
	{
	    case GCFunction:
	    {
		CARD8 newalu;
		NEXTVAL(CARD8, newalu);
		if (newalu <= GXset)
		    pGC->alu = newalu;
		else
		{
		    clientErrorValue = newalu;
		    error = BadValue;
		}
		break;
	    }
	    case GCPlaneMask:
		NEXTVAL(unsigned long, pGC->planemask);
		break;
	    case GCForeground:
		NEXTVAL(unsigned long, pGC->fgPixel);
		/*
		 * this is for CreateGC
		 */
		if (!pGC->tileIsPixel && !pGC->tile.pixmap)
		{
		    pGC->tileIsPixel = TRUE;
		    pGC->tile.pixel = pGC->fgPixel;
		}
		break;
	    case GCBackground:
		NEXTVAL(unsigned long, pGC->bgPixel);
		break;
	    case GCLineWidth:		/* ??? line width is a CARD16 */
		 NEXTVAL(CARD16, pGC->lineWidth);
		break;
	    case GCLineStyle:
	    {
		unsigned int newlinestyle;
		NEXTVAL(unsigned int, newlinestyle);
		if (newlinestyle <= LineDoubleDash)
		    pGC->lineStyle = newlinestyle;
		else
		{
		    clientErrorValue = newlinestyle;
		    error = BadValue;
		}
		break;
	    }
	    case GCCapStyle:
	    {
		unsigned int newcapstyle;
		NEXTVAL(unsigned int, newcapstyle);
		if (newcapstyle <= CapProjecting)
		    pGC->capStyle = newcapstyle;
		else
		{
		    clientErrorValue = newcapstyle;
		    error = BadValue;
		}
		break;
	    }
	    case GCJoinStyle:
	    {
		unsigned int newjoinstyle;
		NEXTVAL(unsigned int, newjoinstyle);
		if (newjoinstyle <= JoinBevel)
		    pGC->joinStyle = newjoinstyle;
		else
		{
		    clientErrorValue = newjoinstyle;
		    error = BadValue;
		}
		break;
	    }
	    case GCFillStyle:
	    {
		unsigned int newfillstyle;
		NEXTVAL(unsigned int, newfillstyle);
		if (newfillstyle <= FillOpaqueStippled)
		    pGC->fillStyle = newfillstyle;
		else
		{
		    clientErrorValue = newfillstyle;
		    error = BadValue;
		}
		break;
	    }
	    case GCFillRule:
	    {
		unsigned int newfillrule;
		NEXTVAL(unsigned int, newfillrule);
		if (newfillrule <= WindingRule)
		    pGC->fillRule = newfillrule;
		else
		{
		    clientErrorValue = newfillrule;
		    error = BadValue;
		}
		break;
	    }
	    case GCTile:
	    {
		XID newpix = 0;
		if (pUnion)
		{
		    NEXT_PTR(PixmapPtr, pPixmap);
		}
		else
		{
		    NEXTVAL(XID, newpix);
		    pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
					newpix, RT_PIXMAP, SecurityReadAccess);
		}
		if (pPixmap)
		{
		    if ((pPixmap->drawable.depth != pGC->depth) ||
			(pPixmap->drawable.pScreen != pGC->pScreen))
		    {
			error = BadMatch;
		    }
		    else
		    {
			pPixmap->refcnt++;
			if (!pGC->tileIsPixel)
			    (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
			pGC->tileIsPixel = FALSE;
			pGC->tile.pixmap = pPixmap;
		    }
		}
		else
		{
		    clientErrorValue = newpix;
		    error = BadPixmap;
		}
		break;
	    }
	    case GCStipple:
	    {
		XID newstipple = 0;
		if (pUnion)
		{
		    NEXT_PTR(PixmapPtr, pPixmap);
		}
		else
		{
		    NEXTVAL(XID, newstipple)
		    pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
				newstipple, RT_PIXMAP, SecurityReadAccess);
		}
		if (pPixmap)
		{
		    if ((pPixmap->drawable.depth != 1) ||
			(pPixmap->drawable.pScreen != pGC->pScreen))
		    {
			error = BadMatch;
		    }
		    else
		    {
			pPixmap->refcnt++;
			if (pGC->stipple)
			    (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
			pGC->stipple = pPixmap;
		    }
		}
		else
		{
		    clientErrorValue = newstipple;
		    error = BadPixmap;
		}
		break;
	    }
	    case GCTileStipXOrigin:
		NEXTVAL(INT16, pGC->patOrg.x);
		break;
	    case GCTileStipYOrigin:
		NEXTVAL(INT16, pGC->patOrg.y);
		break;
	    case GCFont:
    	    {
		FontPtr	pFont;
		XID newfont = 0;
		if (pUnion)
		{
		    NEXT_PTR(FontPtr, pFont);
		}
		else
		{
		    NEXTVAL(XID, newfont)
		    pFont = (FontPtr)SecurityLookupIDByType(client, newfont,
						RT_FONT, SecurityReadAccess);
		}
		if (pFont)
		{
		    pFont->refcnt++;
		    if (pGC->font)
    		        CloseFont(pGC->font, (Font)0);
		    pGC->font = pFont;
		 }
		else
		{
		    clientErrorValue = newfont;
		    error = BadFont;
		}
		break;
	    }
	    case GCSubwindowMode:
	    {
		unsigned int newclipmode;
		NEXTVAL(unsigned int, newclipmode);
		if (newclipmode <= IncludeInferiors)
		    pGC->subWindowMode = newclipmode;
		else
		{
		    clientErrorValue = newclipmode;
		    error = BadValue;
		}
		break;
	    }
	    case GCGraphicsExposures:
    	    {
		unsigned int newge;
		NEXTVAL(unsigned int, newge);
		if (newge <= xTrue)
		    pGC->graphicsExposures = newge;
		else
		{
		    clientErrorValue = newge;
		    error = BadValue;
		}
		break;
	    }
	    case GCClipXOrigin:
		NEXTVAL(INT16, pGC->clipOrg.x);
		break;
	    case GCClipYOrigin:
		NEXTVAL(INT16, pGC->clipOrg.y);
		break;
	    case GCClipMask:
	    {
		Pixmap pid = 0;
		int    clipType = 0;

		if (pUnion)
		{
		    NEXT_PTR(PixmapPtr, pPixmap);
		}
		else
		{
		    NEXTVAL(Pixmap, pid)
		    if (pid == None)
		    {
			clipType = CT_NONE;
			pPixmap = NullPixmap;
		    }
		    else
		        pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
					pid, RT_PIXMAP, SecurityReadAccess);
		}

		if (pPixmap)
		{
		    if ((pPixmap->drawable.depth != 1) ||
			(pPixmap->drawable.pScreen != pGC->pScreen))
		    {
			error = BadMatch;
		    }
		    else
		    {
			clipType = CT_PIXMAP;
			pPixmap->refcnt++;
		    }
		}
		else if (!pUnion && (pid != None))
		{
		    clientErrorValue = pid;
		    error = BadPixmap;
		}
		if(error == Success)
		{
		    (*pGC->funcs->ChangeClip)(pGC, clipType,
					      (pointer)pPixmap, 0);
		}
		break;
	    }
	    case GCDashOffset:
		NEXTVAL(INT16, pGC->dashOffset);
		break;
	    case GCDashList:
	    {
		CARD8 newdash;
		NEXTVAL(CARD8, newdash);
		if (newdash == 4)
		{
		    if (pGC->dash != DefaultDash)
		    {
			xfree(pGC->dash);
			pGC->numInDashList = 2;
			pGC->dash = DefaultDash;
		    }
		}
		else if (newdash != 0)
 		{
		    unsigned char *dash;

		    dash = (unsigned char *)xalloc(2 * sizeof(unsigned char));
		    if (dash)
		    {
			if (pGC->dash != DefaultDash)
			    xfree(pGC->dash);
			pGC->numInDashList = 2;
			pGC->dash = dash;
			dash[0] = newdash;
			dash[1] = newdash;
		    }
		    else
			error = BadAlloc;
		}
 		else
		{
		   clientErrorValue = newdash;
		   error = BadValue;
		}
		break;
	    }
	    case GCArcMode:
	    {
		unsigned int newarcmode;
		NEXTVAL(unsigned int, newarcmode);
		if (newarcmode <= ArcPieSlice)
		    pGC->arcMode = newarcmode;
		else
		{
		    clientErrorValue = newarcmode;
		    error = BadValue;
		}
		break;
	    }
	    default:
		clientErrorValue = maskQ;
		error = BadValue;
		break;
	}
    } /* end while mask && !error */

    if (pGC->fillStyle == FillTiled && pGC->tileIsPixel)
    {
	if (!CreateDefaultTile (pGC))
	{
	    pGC->fillStyle = FillSolid;
	    error = BadAlloc;
	}
    }
    (*pGC->funcs->ChangeGC)(pGC, maskQ);
    return error;
}
Пример #7
0
int
ChangeGC(ClientPtr client, GC * pGC, BITS32 mask, ChangeGCValPtr pUnion)
{
    BITS32 index2;
    int error = 0;
    PixmapPtr pPixmap;
    BITS32 maskQ;

    assert(pUnion);
    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;

    maskQ = mask;               /* save these for when we walk the GCque */
    while (mask && !error) {
        index2 = (BITS32) lowbit(mask);
        mask &= ~index2;
        pGC->stateChanges |= index2;
        switch (index2) {
        case GCFunction:
        {
            CARD8 newalu;
            NEXTVAL(CARD8, newalu);

            if (newalu <= GXset)
                pGC->alu = newalu;
            else {
                if (client)
                    client->errorValue = newalu;
                error = BadValue;
            }
            break;
        }
        case GCPlaneMask:
            NEXTVAL(unsigned long, pGC->planemask);

            break;
        case GCForeground:
            NEXTVAL(unsigned long, pGC->fgPixel);

            /*
             * this is for CreateGC
             */
            if (!pGC->tileIsPixel && !pGC->tile.pixmap) {
                pGC->tileIsPixel = TRUE;
                pGC->tile.pixel = pGC->fgPixel;
            }
            break;
        case GCBackground:
            NEXTVAL(unsigned long, pGC->bgPixel);

            break;
        case GCLineWidth:      /* ??? line width is a CARD16 */
            NEXTVAL(CARD16, pGC->lineWidth);

            break;
        case GCLineStyle:
        {
            unsigned int newlinestyle;
            NEXTVAL(unsigned int, newlinestyle);

            if (newlinestyle <= LineDoubleDash)
                pGC->lineStyle = newlinestyle;
            else {
                if (client)
                    client->errorValue = newlinestyle;
                error = BadValue;
            }
            break;
        }
        case GCCapStyle:
        {
            unsigned int newcapstyle;
            NEXTVAL(unsigned int, newcapstyle);

            if (newcapstyle <= CapProjecting)
                pGC->capStyle = newcapstyle;
            else {
                if (client)
                    client->errorValue = newcapstyle;
                error = BadValue;
            }
            break;
        }
        case GCJoinStyle:
        {
            unsigned int newjoinstyle;
            NEXTVAL(unsigned int, newjoinstyle);

            if (newjoinstyle <= JoinBevel)
                pGC->joinStyle = newjoinstyle;
            else {
                if (client)
                    client->errorValue = newjoinstyle;
                error = BadValue;
            }
            break;
        }
        case GCFillStyle:
        {
            unsigned int newfillstyle;
            NEXTVAL(unsigned int, newfillstyle);

            if (newfillstyle <= FillOpaqueStippled)
                pGC->fillStyle = newfillstyle;
            else {
                if (client)
                    client->errorValue = newfillstyle;
                error = BadValue;
            }
            break;
        }
        case GCFillRule:
        {
            unsigned int newfillrule;
            NEXTVAL(unsigned int, newfillrule);

            if (newfillrule <= WindingRule)
                pGC->fillRule = newfillrule;
            else {
                if (client)
                    client->errorValue = newfillrule;
                error = BadValue;
            }
            break;
        }
        case GCTile:
            NEXT_PTR(PixmapPtr, pPixmap);

            if ((pPixmap->drawable.depth != pGC->depth) ||
                (pPixmap->drawable.pScreen != pGC->pScreen)) {
                error = BadMatch;
            }
            else {
                pPixmap->refcnt++;
                if (!pGC->tileIsPixel)
                    (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap);
                pGC->tileIsPixel = FALSE;
                pGC->tile.pixmap = pPixmap;
            }
            break;
        case GCStipple:
            NEXT_PTR(PixmapPtr, pPixmap);

            if (pPixmap && ((pPixmap->drawable.depth != 1) ||
                            (pPixmap->drawable.pScreen != pGC->pScreen)))
            {
                error = BadMatch;
            }
            else {
                if (pPixmap)
                    pPixmap->refcnt++;
                if (pGC->stipple)
                    (*pGC->pScreen->DestroyPixmap) (pGC->stipple);
                pGC->stipple = pPixmap;
            }
            break;
        case GCTileStipXOrigin:
            NEXTVAL(INT16, pGC->patOrg.x);

            break;
        case GCTileStipYOrigin:
            NEXTVAL(INT16, pGC->patOrg.y);

            break;
        case GCFont:
        {
            FontPtr pFont;
            NEXT_PTR(FontPtr, pFont);

            pFont->refcnt++;
            if (pGC->font)
                CloseFont(pGC->font, (Font) 0);
            pGC->font = pFont;
            break;
        }
        case GCSubwindowMode:
        {
            unsigned int newclipmode;
            NEXTVAL(unsigned int, newclipmode);

            if (newclipmode <= IncludeInferiors)
                pGC->subWindowMode = newclipmode;
            else {
                if (client)
                    client->errorValue = newclipmode;
                error = BadValue;
            }
            break;
        }
        case GCGraphicsExposures:
        {
            unsigned int newge;
            NEXTVAL(unsigned int, newge);

            if (newge <= xTrue)
                pGC->graphicsExposures = newge;
            else {
                if (client)
                    client->errorValue = newge;
                error = BadValue;
            }
            break;
        }
        case GCClipXOrigin:
            NEXTVAL(INT16, pGC->clipOrg.x);

            break;
        case GCClipYOrigin:
            NEXTVAL(INT16, pGC->clipOrg.y);

            break;
        case GCClipMask:
            NEXT_PTR(PixmapPtr, pPixmap);

            if (pPixmap) {
                if ((pPixmap->drawable.depth != 1) ||
                    (pPixmap->drawable.pScreen != pGC->pScreen)) {
                    error = BadMatch;
                    break;
                }
                pPixmap->refcnt++;
            }
            (*pGC->funcs->ChangeClip) (pGC, pPixmap ? CT_PIXMAP : CT_NONE,
                                       (void *) pPixmap, 0);
            break;
        case GCDashOffset:
            NEXTVAL(INT16, pGC->dashOffset);

            break;
        case GCDashList:
        {
            CARD8 newdash;
            NEXTVAL(CARD8, newdash);

            if (newdash == 4) {
                if (pGC->dash != DefaultDash) {
                    free(pGC->dash);
                    pGC->numInDashList = 2;
                    pGC->dash = DefaultDash;
                }
            }
            else if (newdash != 0) {
                unsigned char *dash;

                dash = malloc(2 * sizeof(unsigned char));
                if (dash) {
                    if (pGC->dash != DefaultDash)
                        free(pGC->dash);
                    pGC->numInDashList = 2;
                    pGC->dash = dash;
                    dash[0] = newdash;
                    dash[1] = newdash;
                }
                else
                    error = BadAlloc;
            }
            else {
                if (client)
                    client->errorValue = newdash;
                error = BadValue;
            }
            break;
        }
        case GCArcMode:
        {
            unsigned int newarcmode;
            NEXTVAL(unsigned int, newarcmode);

            if (newarcmode <= ArcPieSlice)
                pGC->arcMode = newarcmode;
            else {
                if (client)
                    client->errorValue = newarcmode;
                error = BadValue;
            }
            break;
        }
        default:
            if (client)
                client->errorValue = maskQ;
            error = BadValue;
            break;
        }
    }                           /* end while mask && !error */

    if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) {
        if (!CreateDefaultTile(pGC)) {
            pGC->fillStyle = FillSolid;
            error = BadAlloc;
        }
    }
    (*pGC->funcs->ChangeGC) (pGC, maskQ);
    return error;
}
Пример #8
0
void
init_cfg(Oid id, TSCfgInfo * cfg)
{
    Oid			arg[2];
    bool		isnull;
    Datum		pars[2];
    int			stat,
                i,
                j;
    text	   *ptr;
    text	   *prsname = NULL;
    char	   *nsp = get_namespace(TSNSP_FunctionOid);
    char		buf[1024];
    MemoryContext oldcontext;
    void	   *plan;

    arg[0] = OIDOID;
    arg[1] = OIDOID;
    pars[0] = ObjectIdGetDatum(id);
    pars[1] = ObjectIdGetDatum(id);

    memset(cfg, 0, sizeof(TSCfgInfo));
    SPI_connect();

    sprintf(buf, "select prs_name from %s.pg_ts_cfg where oid = $1", nsp);
    plan = SPI_prepare(buf, 1, arg);
    if (!plan)
        ts_error(ERROR, "SPI_prepare() failed");

    stat = SPI_execp(plan, pars, " ", 1);
    if (stat < 0)
        ts_error(ERROR, "SPI_execp return %d", stat);
    if (SPI_processed > 0)
    {
        prsname = (text *) DatumGetPointer(
                      SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)
                  );
        oldcontext = MemoryContextSwitchTo(TopMemoryContext);
        prsname = ptextdup(prsname);
        MemoryContextSwitchTo(oldcontext);

        cfg->id = id;
    }
    else
        ts_error(ERROR, "No tsearch cfg with id %d", id);

    SPI_freeplan(plan);

    arg[0] = TEXTOID;
    sprintf(buf, "select lt.tokid, map.dict_name from %s.pg_ts_cfgmap as map, %s.pg_ts_cfg as cfg, %s.token_type( $1 ) as lt where lt.alias =  map.tok_alias and map.ts_name = cfg.ts_name and cfg.oid= $2 order by lt.tokid desc;", nsp, nsp, nsp);
    plan = SPI_prepare(buf, 2, arg);
    if (!plan)
        ts_error(ERROR, "SPI_prepare() failed");

    pars[0] = PointerGetDatum(prsname);
    stat = SPI_execp(plan, pars, " ", 0);
    if (stat < 0)
        ts_error(ERROR, "SPI_execp return %d", stat);
    if (SPI_processed <= 0)
        ts_error(ERROR, "No parser with id %d", id);

    for (i = 0; i < SPI_processed; i++)
    {
        int			lexid = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull));
        ArrayType  *toasted_a = (ArrayType *) PointerGetDatum(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnull));
        ArrayType  *a;

        if (!cfg->map)
        {
            cfg->len = lexid + 1;
            cfg->map = (ListDictionary *) malloc(sizeof(ListDictionary) * cfg->len);
            if (!cfg->map)
                ereport(ERROR,
                        (errcode(ERRCODE_OUT_OF_MEMORY),
                         errmsg("out of memory")));
            memset(cfg->map, 0, sizeof(ListDictionary) * cfg->len);
        }

        if (isnull)
            continue;

        a = (ArrayType *) PointerGetDatum(PG_DETOAST_DATUM(DatumGetPointer(toasted_a)));

        if (ARR_NDIM(a) != 1)
            ts_error(ERROR, "Wrong dimension");
        if (ARRNELEMS(a) < 1)
            continue;
        if (ARR_HASNULL(a))
            ts_error(ERROR, "Array must not contain nulls");

        cfg->map[lexid].len = ARRNELEMS(a);
        cfg->map[lexid].dict_id = (Datum *) malloc(sizeof(Datum) * cfg->map[lexid].len);
        if (!cfg->map[lexid].dict_id)
            ts_error(ERROR, "No memory");

        memset(cfg->map[lexid].dict_id, 0, sizeof(Datum) * cfg->map[lexid].len);
        ptr = (text *) ARR_DATA_PTR(a);
        oldcontext = MemoryContextSwitchTo(TopMemoryContext);
        for (j = 0; j < cfg->map[lexid].len; j++)
        {
            cfg->map[lexid].dict_id[j] = PointerGetDatum(ptextdup(ptr));
            ptr = NEXTVAL(ptr);
        }
        MemoryContextSwitchTo(oldcontext);

        if (a != toasted_a)
            pfree(a);
    }

    SPI_freeplan(plan);
    SPI_finish();
    cfg->prs_id = name2id_prs(prsname);
    pfree(prsname);
    pfree(nsp);
    for (i = 0; i < cfg->len; i++)
    {
        for (j = 0; j < cfg->map[i].len; j++)
        {
            ptr = (text *) DatumGetPointer(cfg->map[i].dict_id[j]);
            cfg->map[i].dict_id[j] = ObjectIdGetDatum(name2id_dict(ptr));
            pfree(ptr);
        }
    }
}