Ejemplo n.º 1
0
/*
 * init_params: process the options list of CREATE or ALTER SEQUENCE,
 * and store the values into appropriate fields of *new___.  Also set
 * *owned_by to any OWNED BY option, or to NIL if there is none.
 *
 * If isInit is true, fill any unspecified options with default values;
 * otherwise, do not change existing options that aren't explicitly overridden.
 */
static void
init_params(List *options, bool isInit,
			Form_pg_sequence new___, List **owned_by)
{
	DefElem    *start_value = NULL;
	DefElem    *restart_value = NULL;
	DefElem    *increment_by = NULL;
	DefElem    *max_value = NULL;
	DefElem    *min_value = NULL;
	DefElem    *cache_value = NULL;
	DefElem    *is_cycled = NULL;
	ListCell   *option;

	*owned_by = NIL;

	foreach(option, options)
	{
		DefElem    *defel = (DefElem *) lfirst(option);

		if (strcmp(defel->defname, "increment") == 0)
		{
			if (increment_by)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			increment_by = defel;
		}
		else if (strcmp(defel->defname, "start") == 0)
		{
			if (start_value)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			start_value = defel;
		}
		else if (strcmp(defel->defname, "restart") == 0)
		{
			if (restart_value)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			restart_value = defel;
		}
		else if (strcmp(defel->defname, "maxvalue") == 0)
		{
			if (max_value)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			max_value = defel;
		}
		else if (strcmp(defel->defname, "minvalue") == 0)
		{
			if (min_value)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			min_value = defel;
		}
		else if (strcmp(defel->defname, "cache") == 0)
		{
			if (cache_value)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			cache_value = defel;
		}
		else if (strcmp(defel->defname, "cycle") == 0)
		{
			if (is_cycled)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			is_cycled = defel;
		}
		else if (strcmp(defel->defname, "owned_by") == 0)
		{
			if (*owned_by)
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("conflicting or redundant options")));
			*owned_by = defGetQualifiedName(defel);
		}
		else
			elog(ERROR, "option \"%s\" not recognized",
				 defel->defname);
	}
Ejemplo n.º 2
0
/*
 *	DefineAggregate
 *
 * "oldstyle" signals the old (pre-8.2) style where the aggregate input type
 * is specified by a BASETYPE element in the parameters.  Otherwise,
 * "args" is a pair, whose first element is a list of FunctionParameter structs
 * defining the agg's arguments (both direct and aggregated), and whose second
 * element is an Integer node with the number of direct args, or -1 if this
 * isn't an ordered-set aggregate.
 * "parameters" is a list of DefElem representing the agg's definition clauses.
 */
ObjectAddress
DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                const char *queryString)
{
    char	   *aggName;
    Oid			aggNamespace;
    AclResult	aclresult;
    char		aggKind = AGGKIND_NORMAL;
    List	   *transfuncName = NIL;
    List	   *finalfuncName = NIL;
    List	   *combinefuncName = NIL;
    List	   *serialfuncName = NIL;
    List	   *deserialfuncName = NIL;
    List	   *mtransfuncName = NIL;
    List	   *minvtransfuncName = NIL;
    List	   *mfinalfuncName = NIL;
    bool		finalfuncExtraArgs = false;
    bool		mfinalfuncExtraArgs = false;
    List	   *sortoperatorName = NIL;
    TypeName   *baseType = NULL;
    TypeName   *transType = NULL;
    TypeName   *mtransType = NULL;
    int32		transSpace = 0;
    int32		mtransSpace = 0;
    char	   *initval = NULL;
    char	   *minitval = NULL;
    char	   *parallel = NULL;
    int			numArgs;
    int			numDirectArgs = 0;
    oidvector  *parameterTypes;
    ArrayType  *allParameterTypes;
    ArrayType  *parameterModes;
    ArrayType  *parameterNames;
    List	   *parameterDefaults;
    Oid			variadicArgType;
    Oid			transTypeId;
    Oid			mtransTypeId = InvalidOid;
    char		transTypeType;
    char		mtransTypeType = 0;
    char		proparallel = PROPARALLEL_UNSAFE;
    ListCell   *pl;

    /* Convert list of names to a name and namespace */
    aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName);

    /* Check we have creation rights in target namespace */
    aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                       get_namespace_name(aggNamespace));

    /* Deconstruct the output of the aggr_args grammar production */
    if (!oldstyle)
    {
        Assert(list_length(args) == 2);
        numDirectArgs = intVal(lsecond(args));
        if (numDirectArgs >= 0)
            aggKind = AGGKIND_ORDERED_SET;
        else
            numDirectArgs = 0;
        args = (List *) linitial(args);
    }

    /* Examine aggregate's definition clauses */
    foreach(pl, parameters)
    {
        DefElem    *defel = (DefElem *) lfirst(pl);

        /*
         * sfunc1, stype1, and initcond1 are accepted as obsolete spellings
         * for sfunc, stype, initcond.
         */
        if (pg_strcasecmp(defel->defname, "sfunc") == 0)
            transfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "sfunc1") == 0)
            transfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "finalfunc") == 0)
            finalfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "combinefunc") == 0)
            combinefuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "serialfunc") == 0)
            serialfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "deserialfunc") == 0)
            deserialfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "msfunc") == 0)
            mtransfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "minvfunc") == 0)
            minvtransfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "mfinalfunc") == 0)
            mfinalfuncName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "finalfunc_extra") == 0)
            finalfuncExtraArgs = defGetBoolean(defel);
        else if (pg_strcasecmp(defel->defname, "mfinalfunc_extra") == 0)
            mfinalfuncExtraArgs = defGetBoolean(defel);
        else if (pg_strcasecmp(defel->defname, "sortop") == 0)
            sortoperatorName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "basetype") == 0)
            baseType = defGetTypeName(defel);
        else if (pg_strcasecmp(defel->defname, "hypothetical") == 0)
        {
            if (defGetBoolean(defel))
            {
                if (aggKind == AGGKIND_NORMAL)
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                             errmsg("only ordered-set aggregates can be hypothetical")));
                aggKind = AGGKIND_HYPOTHETICAL;
            }
        }
        else if (pg_strcasecmp(defel->defname, "stype") == 0)
            transType = defGetTypeName(defel);
        else if (pg_strcasecmp(defel->defname, "stype1") == 0)
            transType = defGetTypeName(defel);
        else if (pg_strcasecmp(defel->defname, "sspace") == 0)
            transSpace = defGetInt32(defel);
        else if (pg_strcasecmp(defel->defname, "mstype") == 0)
            mtransType = defGetTypeName(defel);
        else if (pg_strcasecmp(defel->defname, "msspace") == 0)
            mtransSpace = defGetInt32(defel);
        else if (pg_strcasecmp(defel->defname, "initcond") == 0)
            initval = defGetString(defel);
        else if (pg_strcasecmp(defel->defname, "initcond1") == 0)
            initval = defGetString(defel);
        else if (pg_strcasecmp(defel->defname, "minitcond") == 0)
            minitval = defGetString(defel);
        else if (pg_strcasecmp(defel->defname, "parallel") == 0)
            parallel = defGetString(defel);
        else
            ereport(WARNING,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("aggregate attribute \"%s\" not recognized",
                            defel->defname)));
    }
Ejemplo n.º 3
0
/*
 *	DefineFileSystem
 */
void
DefineFileSystem(List *name, List *parameters, Oid newOid, bool trusted)
{
	char	   *fsysName;
	Oid			fsysNamespace;
	AclResult	aclresult;
	List	   *funcNames[FSYS_FUNC_TOTALNUM];
	char	   *fsysLibFile = NULL;
	int			funcNum = 0;
	ListCell   *pl;
	Oid			fsysOid;

	/* Convert list of names to a name and namespace */
	fsysNamespace = QualifiedNameGetCreationNamespace(name, &fsysName);

	/* Check we have creation rights in target namespace */
	aclresult = pg_namespace_aclcheck(fsysNamespace, GetUserId(), ACL_CREATE);
	if (aclresult != ACLCHECK_OK)
		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
					   get_namespace_name(fsysNamespace));

	for(int i = 0; i < FSYS_FUNC_TOTALNUM; i++)
		funcNames[i] = NIL;

	foreach(pl, parameters)
	{
		DefElem    *defel = (DefElem *) lfirst(pl);
		int funcType;

		if (pg_strcasecmp(defel->defname, fsysLibFileName) == 0)
		{
			if(fsysLibFile == NULL)
			{
				fsysLibFile = strVal(linitial(defGetQualifiedName(defel)));
			}
			else
			{
				ereport(ERROR,
						(errcode(ERRCODE_SYNTAX_ERROR),
						 errmsg("filesystem attribute \"%s\" duplicated",
								defel->defname)));
			}
			continue;
		}

		for(funcType = 0; funcType < FSYS_FUNC_TOTALNUM; funcType++)
		{
			if(pg_strcasecmp(defel->defname, fsys_func_type_to_name(funcType)) == 0)
				break;
		}
		if (funcType >= FSYS_FUNC_TOTALNUM)
			ereport(ERROR,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("filesystem attribute \"%s\" not recognized",
							defel->defname)));
		if(funcNames[funcType] == NIL)
			funcNames[funcType] = defGetQualifiedName(defel);
		else
			ereport(ERROR,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("filesystem function \"%s\" duplicated",
							defel->defname)));
		funcNum++;
	}
Ejemplo n.º 4
0
/*
 * DefineOperator
 *		this function extracts all the information from the
 *		parameter list generated by the parser and then has
 *		OperatorCreate() do all the actual work.
 *
 * 'parameters' is a list of DefElem
 */
ObjectAddress
DefineOperator(List *names, List *parameters)
{
    char	   *oprName;
    Oid			oprNamespace;
    AclResult	aclresult;
    bool		canMerge = false;		/* operator merges */
    bool		canHash = false;	/* operator hashes */
    List	   *functionName = NIL;		/* function for operator */
    TypeName   *typeName1 = NULL;		/* first type name */
    TypeName   *typeName2 = NULL;		/* second type name */
    Oid			typeId1 = InvalidOid;	/* types converted to OID */
    Oid			typeId2 = InvalidOid;
    Oid			rettype;
    List	   *commutatorName = NIL;	/* optional commutator operator name */
    List	   *negatorName = NIL;		/* optional negator operator name */
    List	   *restrictionName = NIL;	/* optional restrict. sel. procedure */
    List	   *joinName = NIL; /* optional join sel. procedure */
    Oid			functionOid;	/* functions converted to OID */
    Oid			restrictionOid;
    Oid			joinOid;
    Oid			typeId[2];		/* to hold left and right arg */
    int			nargs;
    ListCell   *pl;

    /* Convert list of names to a name and namespace */
    oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);

    /* Check we have creation rights in target namespace */
    aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                       get_namespace_name(oprNamespace));

    /*
     * loop over the definition list and extract the information we need.
     */
    foreach(pl, parameters)
    {
        DefElem    *defel = (DefElem *) lfirst(pl);

        if (pg_strcasecmp(defel->defname, "leftarg") == 0)
        {
            typeName1 = defGetTypeName(defel);
            if (typeName1->setof)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                         errmsg("SETOF type not allowed for operator argument")));
        }
        else if (pg_strcasecmp(defel->defname, "rightarg") == 0)
        {
            typeName2 = defGetTypeName(defel);
            if (typeName2->setof)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                         errmsg("SETOF type not allowed for operator argument")));
        }
        else if (pg_strcasecmp(defel->defname, "procedure") == 0)
            functionName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "commutator") == 0)
            commutatorName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "negator") == 0)
            negatorName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "restrict") == 0)
            restrictionName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "join") == 0)
            joinName = defGetQualifiedName(defel);
        else if (pg_strcasecmp(defel->defname, "hashes") == 0)
            canHash = defGetBoolean(defel);
        else if (pg_strcasecmp(defel->defname, "merges") == 0)
            canMerge = defGetBoolean(defel);
        /* These obsolete options are taken as meaning canMerge */
        else if (pg_strcasecmp(defel->defname, "sort1") == 0)
            canMerge = true;
        else if (pg_strcasecmp(defel->defname, "sort2") == 0)
            canMerge = true;
        else if (pg_strcasecmp(defel->defname, "ltcmp") == 0)
            canMerge = true;
        else if (pg_strcasecmp(defel->defname, "gtcmp") == 0)
            canMerge = true;
        else
        {
            /* WARNING, not ERROR, for historical backwards-compatibility */
            ereport(WARNING,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("operator attribute \"%s\" not recognized",
                            defel->defname)));
        }
    }
Ejemplo n.º 5
0
/*
 *	DefineAggregate
 *
 * "oldstyle" signals the old (pre-8.2) style where the aggregate input type
 * is specified by a BASETYPE element in the parameters.  Otherwise,
 * "args" defines the input type(s).
 */
void
DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
{
	char	   *aggName;
	Oid			aggNamespace;
	AclResult	aclresult;
	List	   *transfuncName = NIL;
	List	   *finalfuncName = NIL;
	List	   *sortoperatorName = NIL;
	TypeName   *baseType = NULL;
	TypeName   *transType = NULL;
#ifdef XCP
	TypeName   *collectType = NULL;
#endif
	char	   *initval = NULL;
#ifdef PGXC
	List	   *collectfuncName = NIL;
	char	   *initcollect = NULL;
#endif
	Oid		   *aggArgTypes;
	int			numArgs;
	Oid			transTypeId;
#ifdef XCP
	Oid			collectTypeId;
#endif
	ListCell   *pl;

	/* Convert list of names to a name and namespace */
	aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName);

	/* Check we have creation rights in target namespace */
	aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE);
	if (aclresult != ACLCHECK_OK)
		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
					   get_namespace_name(aggNamespace));

	foreach(pl, parameters)
	{
		DefElem    *defel = (DefElem *) lfirst(pl);

		/*
		 * sfunc1, stype1, and initcond1 are accepted as obsolete spellings
		 * for sfunc, stype, initcond.
		 */
		if (pg_strcasecmp(defel->defname, "sfunc") == 0)
			transfuncName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "sfunc1") == 0)
			transfuncName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "finalfunc") == 0)
			finalfuncName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "sortop") == 0)
			sortoperatorName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "basetype") == 0)
			baseType = defGetTypeName(defel);
		else if (pg_strcasecmp(defel->defname, "stype") == 0)
			transType = defGetTypeName(defel);
		else if (pg_strcasecmp(defel->defname, "stype1") == 0)
			transType = defGetTypeName(defel);
#ifdef XCP
		else if (pg_strcasecmp(defel->defname, "ctype") == 0)
			collectType = defGetTypeName(defel);
#endif
		else if (pg_strcasecmp(defel->defname, "initcond") == 0)
			initval = defGetString(defel);
		else if (pg_strcasecmp(defel->defname, "initcond1") == 0)
			initval = defGetString(defel);
#ifdef PGXC
		else if (pg_strcasecmp(defel->defname, "cfunc") == 0)
			collectfuncName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "initcollect") == 0)
			initcollect = defGetString(defel);
#endif
		else
			ereport(WARNING,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("aggregate attribute \"%s\" not recognized",
							defel->defname)));
	}
Ejemplo n.º 6
0
/*
 * DefineOperator
 *		this function extracts all the information from the
 *		parameter list generated by the parser and then has
 *		OperatorCreate() do all the actual work.
 *
 * 'parameters' is a list of DefElem
 */
void
DefineOperator(List *names, List *parameters)
{
	char	   *oprName;
	Oid			oprNamespace;
	AclResult	aclresult;
	bool		canHash = false;	/* operator hashes */
	bool		canMerge = false;		/* operator merges */
	List	   *functionName = NIL;		/* function for operator */
	TypeName   *typeName1 = NULL;		/* first type name */
	TypeName   *typeName2 = NULL;		/* second type name */
	Oid			typeId1 = InvalidOid;	/* types converted to OID */
	Oid			typeId2 = InvalidOid;
	List	   *commutatorName = NIL;	/* optional commutator operator
										 * name */
	List	   *negatorName = NIL;		/* optional negator operator name */
	List	   *restrictionName = NIL;	/* optional restrict. sel.
										 * procedure */
	List	   *joinName = NIL; /* optional join sel. procedure */
	List	   *leftSortName = NIL;		/* optional left sort operator */
	List	   *rightSortName = NIL;	/* optional right sort operator */
	List	   *ltCompareName = NIL;	/* optional < compare operator */
	List	   *gtCompareName = NIL;	/* optional > compare operator */
	List	   *pl;

	/* Convert list of names to a name and namespace */
	oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);

	/* Check we have creation rights in target namespace */
	aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE);
	if (aclresult != ACLCHECK_OK)
		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
					   get_namespace_name(oprNamespace));

	/*
	 * loop over the definition list and extract the information we need.
	 */
	foreach(pl, parameters)
	{
		DefElem    *defel = (DefElem *) lfirst(pl);

		if (strcasecmp(defel->defname, "leftarg") == 0)
		{
			typeName1 = defGetTypeName(defel);
			if (typeName1->setof)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
				errmsg("setof type not allowed for operator argument")));
		}
		else if (strcasecmp(defel->defname, "rightarg") == 0)
		{
			typeName2 = defGetTypeName(defel);
			if (typeName2->setof)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
				errmsg("setof type not allowed for operator argument")));
		}
		else if (strcasecmp(defel->defname, "procedure") == 0)
			functionName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "commutator") == 0)
			commutatorName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "negator") == 0)
			negatorName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "restrict") == 0)
			restrictionName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "join") == 0)
			joinName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "hashes") == 0)
			canHash = TRUE;
		else if (strcasecmp(defel->defname, "merges") == 0)
			canMerge = TRUE;
		else if (strcasecmp(defel->defname, "sort1") == 0)
			leftSortName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "sort2") == 0)
			rightSortName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "ltcmp") == 0)
			ltCompareName = defGetQualifiedName(defel);
		else if (strcasecmp(defel->defname, "gtcmp") == 0)
			gtCompareName = defGetQualifiedName(defel);
		else
			ereport(WARNING,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("operator attribute \"%s\" not recognized",
							defel->defname)));
	}
Ejemplo n.º 7
0
/*
 * DefineOperator
 *		this function extracts all the information from the
 *		parameter list generated by the parser and then has
 *		OperatorCreate() do all the actual work.
 *
 * 'parameters' is a list of DefElem
 */
Oid
DefineOperator(List *names, List *parameters)
{
	char	   *oprName;
	Oid			oprNamespace;
	AclResult	aclresult;
	bool		canMerge = false;		/* operator merges */
	bool		canHash = false;	/* operator hashes */
	List	   *functionName = NIL;		/* function for operator */
	TypeName   *typeName1 = NULL;		/* first type name */
	TypeName   *typeName2 = NULL;		/* second type name */
	Oid			typeId1 = InvalidOid;	/* types converted to OID */
	Oid			typeId2 = InvalidOid;
	Oid			rettype;
	List	   *commutatorName = NIL;	/* optional commutator operator name */
	List	   *negatorName = NIL;		/* optional negator operator name */
	List	   *restrictionName = NIL;	/* optional restrict. sel. procedure */
	List	   *joinName = NIL; /* optional join sel. procedure */
	Oid			functionOid;	/* functions converted to OID */
	Oid			restrictionOid;
	Oid			joinOid;
	Oid			typeId[5];		/* only need up to 5 args here */
	int			nargs;
	ListCell   *pl;

	/* Convert list of names to a name and namespace */
	oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);

	/*
	 * The SQL standard committee has decided that => should be used for named
	 * parameters; therefore, a future release of PostgreSQL may disallow it
	 * as the name of a user-defined operator.
	 *
	 * Only complain in the QD node, to avoid being too noisy.
	 */
	if (Gp_role != GP_ROLE_EXECUTE && strcmp(oprName, "=>") == 0)
		ereport(WARNING,
				(errmsg("=> is deprecated as an operator name"),
				 errdetail("This name may be disallowed altogether in future versions of PostgreSQL.")));

	/* Check we have creation rights in target namespace */
	aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE);
	if (aclresult != ACLCHECK_OK)
		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
					   get_namespace_name(oprNamespace));

	/*
	 * loop over the definition list and extract the information we need.
	 */
	foreach(pl, parameters)
	{
		DefElem    *defel = (DefElem *) lfirst(pl);

		if (pg_strcasecmp(defel->defname, "leftarg") == 0)
		{
			typeName1 = defGetTypeName(defel);
			if (typeName1->setof)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
					errmsg("SETOF type not allowed for operator argument")));
		}
		else if (pg_strcasecmp(defel->defname, "rightarg") == 0)
		{
			typeName2 = defGetTypeName(defel);
			if (typeName2->setof)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
					errmsg("SETOF type not allowed for operator argument")));
		}
		else if (pg_strcasecmp(defel->defname, "procedure") == 0)
			functionName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "commutator") == 0)
			commutatorName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "negator") == 0)
			negatorName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "restrict") == 0)
			restrictionName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "join") == 0)
			joinName = defGetQualifiedName(defel);
		else if (pg_strcasecmp(defel->defname, "hashes") == 0)
			canHash = defGetBoolean(defel);
		else if (pg_strcasecmp(defel->defname, "merges") == 0)
			canMerge = defGetBoolean(defel);
		/* These obsolete options are taken as meaning canMerge */
		else if (pg_strcasecmp(defel->defname, "sort1") == 0)
			canMerge = true;
		else if (pg_strcasecmp(defel->defname, "sort2") == 0)
			canMerge = true;
		else if (pg_strcasecmp(defel->defname, "ltcmp") == 0)
			canMerge = true;
		else if (pg_strcasecmp(defel->defname, "gtcmp") == 0)
			canMerge = true;
		else
			ereport(WARNING,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("operator attribute \"%s\" not recognized",
							defel->defname)));
	}