Exemplo n.º 1
0
/*
 * to_regprocedure	- converts "proname(args)" to proc OID
 *
 * If the name is not found, we return NULL.
 */
Datum
to_regprocedure(PG_FUNCTION_ARGS)
{
	char	   *pro_name = PG_GETARG_CSTRING(0);
	List	   *names;
	int			nargs;
	Oid			argtypes[FUNC_MAX_ARGS];
	FuncCandidateList clist;

	/*
	 * Parse the name and arguments, look up potential matches in the current
	 * namespace search list, and scan to see which one exactly matches the
	 * given argument types.    (There will not be more than one match.)
	 */
	parseNameAndArgTypes(pro_name, false, &names, &nargs, argtypes);

	clist = FuncnameGetCandidates(names, nargs, NIL, false, false, true);

	for (; clist; clist = clist->next)
	{
		if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
			PG_RETURN_OID(clist->oid);
	}

	PG_RETURN_NULL();
}
Exemplo n.º 2
0
static Oid
findFunc(char *fname)
{
	FuncCandidateList clist,
				ptr;
	Oid			funcid = InvalidOid;
	List	   *names = makeList1(makeString(fname));

	ptr = clist = FuncnameGetCandidates(names, 1);
	freeList(names);

	if (!ptr)
		return funcid;

	while (ptr)
	{
		if (ptr->args[0] == TEXTOID && funcid == InvalidOid)
			funcid = ptr->oid;
		clist = ptr->next;
		pfree(ptr);
		ptr = clist;
	}

	return funcid;
}
Exemplo n.º 3
0
/*
 * regprocout		- converts proc OID to "pro_name"
 */
Datum
regprocout(PG_FUNCTION_ARGS)
{
	RegProcedure proid = PG_GETARG_OID(0);
	char	   *result;
	HeapTuple	proctup;

	if (proid == InvalidOid)
	{
		result = pstrdup("-");
		PG_RETURN_CSTRING(result);
	}

	proctup = SearchSysCache(PROCOID,
							 ObjectIdGetDatum(proid),
							 0, 0, 0);

	if (HeapTupleIsValid(proctup))
	{
		Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
		char	   *proname = NameStr(procform->proname);

		/*
		 * In bootstrap mode, skip the fancy namespace stuff and just return
		 * the proc name.  (This path is only needed for debugging output
		 * anyway.)
		 */
		if (IsBootstrapProcessingMode())
			result = pstrdup(proname);
		else
		{
			char	   *nspname;
			FuncCandidateList clist;

			/*
			 * Would this proc be found (uniquely!) by regprocin? If not,
			 * qualify it.
			 */
			clist = FuncnameGetCandidates(list_make1(makeString(proname)), -1);
			if (clist != NULL && clist->next == NULL &&
				clist->oid == proid)
				nspname = NULL;
			else
				nspname = get_namespace_name(procform->pronamespace);

			result = quote_qualified_identifier(nspname, proname);
		}

		ReleaseSysCache(proctup);
	}
	else
	{
		/* If OID doesn't match any pg_proc entry, return it numerically */
		result = (char *) palloc(NAMEDATALEN);
		snprintf(result, NAMEDATALEN, "%u", proid);
	}

	PG_RETURN_CSTRING(result);
}
Exemplo n.º 4
0
static Oid GetFuncOid(char *s)
{
  FuncCandidateList fcl=FuncnameGetCandidates(
      list_make2(makeString("provsql"),makeString(s)),-1,NIL,false,false,false);
  if(fcl)
    return fcl->oid;    
  else
    return 0;
}
Exemplo n.º 5
0
/*
 * regprocedurein		- converts "proname(args)" to proc OID
 *
 * We also accept a numeric OID, for symmetry with the output routine.
 *
 * '-' signifies unknown (OID 0).  In all other cases, the input must
 * match an existing pg_proc entry.
 */
Datum
regprocedurein(PG_FUNCTION_ARGS)
{
	char	   *pro_name_or_oid = PG_GETARG_CSTRING(0);
	RegProcedure result = InvalidOid;
	List	   *names;
	int			nargs;
	Oid			argtypes[FUNC_MAX_ARGS];
	FuncCandidateList clist;

	/* '-' ? */
	if (strcmp(pro_name_or_oid, "-") == 0)
		PG_RETURN_OID(InvalidOid);

	/* Numeric OID? */
	if (pro_name_or_oid[0] >= '0' &&
		pro_name_or_oid[0] <= '9' &&
		strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
	{
		result = DatumGetObjectId(DirectFunctionCall1(oidin,
										  CStringGetDatum(pro_name_or_oid)));
		PG_RETURN_OID(result);
	}

	/*
	 * Else it's a name and arguments.  Parse the name and arguments, look up
	 * potential matches in the current namespace search list, and scan to see
	 * which one exactly matches the given argument types.	(There will not be
	 * more than one match.)
	 *
	 * XXX at present, this code will not work in bootstrap mode, hence this
	 * datatype cannot be used for any system column that needs to receive
	 * data during bootstrap.
	 */
	parseNameAndArgTypes(pro_name_or_oid, "regprocedurein", false,
						 &names, &nargs, argtypes);

	clist = FuncnameGetCandidates(names, nargs);

	for (; clist; clist = clist->next)
	{
		if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
			break;
	}

	if (clist == NULL)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));

	result = clist->oid;

	PG_RETURN_OID(result);
}
Exemplo n.º 6
0
/*
 * to_regproc	- converts "proname" to proc OID
 *
 * If the name is not found, we return NULL.
 */
Datum
to_regproc(PG_FUNCTION_ARGS)
{
	char	   *pro_name = PG_GETARG_CSTRING(0);
	List	   *names;
	FuncCandidateList clist;

	/*
	 * Parse the name into components and see if it matches any pg_proc
	 * entries in the current search path.
	 */
	names = stringToQualifiedNameList(pro_name);
	clist = FuncnameGetCandidates(names, -1, NIL, false, false, true);

	if (clist == NULL || clist->next != NULL)
		PG_RETURN_NULL();

	PG_RETURN_OID(clist->oid);
}
Exemplo n.º 7
0
/*
 * regprocin		- converts "proname" to proc OID
 *
 * We also accept a numeric OID, for symmetry with the output routine.
 *
 * '-' signifies unknown (OID 0).  In all other cases, the input must
 * match an existing pg_proc entry.
 */
Datum
regprocin(PG_FUNCTION_ARGS)
{
	char	   *pro_name_or_oid = PG_GETARG_CSTRING(0);
	RegProcedure result = InvalidOid;
	List	   *names;
	FuncCandidateList clist;

	/* '-' ? */
	if (strcmp(pro_name_or_oid, "-") == 0)
		PG_RETURN_OID(InvalidOid);

	/* Numeric OID? */
	if (pro_name_or_oid[0] >= '0' &&
		pro_name_or_oid[0] <= '9' &&
		strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
	{
		result = DatumGetObjectId(DirectFunctionCall1(oidin,
										  CStringGetDatum(pro_name_or_oid)));
		PG_RETURN_OID(result);
	}

	/* Else it's a name, possibly schema-qualified */

	/*
	 * In bootstrap mode we assume the given name is not schema-qualified, and
	 * just search pg_proc for a unique match.	This is needed for
	 * initializing other system catalogs (pg_namespace may not exist yet, and
	 * certainly there are no schemas other than pg_catalog).
	 */
	if (IsBootstrapProcessingMode())
	{
		int			matches = 0;
		Relation	hdesc;
		ScanKeyData skey[1];
		SysScanDesc sysscan;
		HeapTuple	tuple;

		ScanKeyInit(&skey[0],
					Anum_pg_proc_proname,
					BTEqualStrategyNumber, F_NAMEEQ,
					CStringGetDatum(pro_name_or_oid));

		hdesc = heap_open(ProcedureRelationId, AccessShareLock);
		sysscan = systable_beginscan(hdesc, ProcedureNameArgsNspIndexId, true,
									 NULL, 1, skey);

		while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
		{
			result = (RegProcedure) HeapTupleGetOid(tuple);
			if (++matches > 1)
				break;
		}

		systable_endscan(sysscan);
		heap_close(hdesc, AccessShareLock);

		if (matches == 0)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));

		else if (matches > 1)
			ereport(ERROR,
					(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
					 errmsg("more than one function named \"%s\"",
							pro_name_or_oid)));

		PG_RETURN_OID(result);
	}

	/*
	 * Normal case: parse the name into components and see if it matches any
	 * pg_proc entries in the current search path.
	 */
	names = stringToQualifiedNameList(pro_name_or_oid);
	clist = FuncnameGetCandidates(names, -1, NIL, false, false, false);

	if (clist == NULL)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
	else if (clist->next != NULL)
		ereport(ERROR,
				(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
				 errmsg("more than one function named \"%s\"",
						pro_name_or_oid)));

	result = clist->oid;

	PG_RETURN_OID(result);
}
Exemplo n.º 8
0
/*
 * regprocin		- converts "proname" to proc OID
 *
 * We also accept a numeric OID, for symmetry with the output routine.
 *
 * '-' signifies unknown (OID 0).  In all other cases, the input must
 * match an existing pg_proc entry.
 */
Datum
regprocin(PG_FUNCTION_ARGS)
{
	char	   *pro_name_or_oid = PG_GETARG_CSTRING(0);
	RegProcedure result = InvalidOid;
	List	   *names;
	FuncCandidateList clist;

	/* '-' ? */
	if (strcmp(pro_name_or_oid, "-") == 0)
		PG_RETURN_OID(InvalidOid);

	/* Numeric OID? */
	if (pro_name_or_oid[0] >= '0' &&
		pro_name_or_oid[0] <= '9' &&
		strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
	{
		result = DatumGetObjectId(DirectFunctionCall1(oidin,
										  CStringGetDatum(pro_name_or_oid)));
		PG_RETURN_OID(result);
	}

	/* Else it's a name, possibly schema-qualified */

	/*
	 * In bootstrap mode we assume the given name is not schema-qualified, and
	 * just search pg_proc for a unique match.	This is needed for
	 * initializing other system catalogs (pg_namespace may not exist yet, and
	 * certainly there are no schemas other than pg_catalog).
	 */
	if (IsBootstrapProcessingMode())
	{
		int			matches = 0;

		result = 
				(RegProcedure) caql_getoid_plus(
						NULL,
						&matches,
						NULL,
						cql("SELECT oid FROM pg_proc "
							" WHERE proname = :1 ",
							CStringGetDatum(pro_name_or_oid)));

		if (matches == 0)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));

		else if (matches > 1)
			ereport(ERROR,
					(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
					 errmsg("more than one function named \"%s\"",
							pro_name_or_oid)));

		PG_RETURN_OID(result);
	}

	/*
	 * Normal case: parse the name into components and see if it matches any
	 * pg_proc entries in the current search path.
	 */
	names = stringToQualifiedNameList(pro_name_or_oid, "regprocin");
	clist = FuncnameGetCandidates(names, -1);

	if (clist == NULL)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
	else if (clist->next != NULL)
		ereport(ERROR,
				(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
				 errmsg("more than one function named \"%s\"",
						pro_name_or_oid)));

	result = clist->oid;

	PG_RETURN_OID(result);
}
Exemplo n.º 9
0
/*
 * regprocout		- converts proc OID to "pro_name"
 */
Datum
regprocout(PG_FUNCTION_ARGS)
{
	RegProcedure proid = PG_GETARG_OID(0);
	char	   *result;
	HeapTuple	proctup;
	cqContext  *pcqCtx;

	if (proid == InvalidOid)
	{
		result = pstrdup("-");
		PG_RETURN_CSTRING(result);
	}

	pcqCtx = caql_beginscan(
			NULL,
			cql("SELECT * FROM pg_proc "
				" WHERE oid = :1 ",
				ObjectIdGetDatum(proid)));

	proctup = caql_getnext(pcqCtx);

	/* XXX XXX select proname, pronamespace from pg_proc */
	if (HeapTupleIsValid(proctup))
	{
		Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
		char	   *proname = NameStr(procform->proname);

		/*
		 * In bootstrap mode, skip the fancy namespace stuff and just return
		 * the proc name.  (This path is only needed for debugging output
		 * anyway.)
		 */
		if (IsBootstrapProcessingMode())
			result = pstrdup(proname);
		else
		{
			char	   *nspname;
			FuncCandidateList clist;

			/*
			 * Would this proc be found (uniquely!) by regprocin? If not,
			 * qualify it.
			 */
			clist = FuncnameGetCandidates(list_make1(makeString(proname)), -1, false, false);
			if (clist != NULL && clist->next == NULL &&
				clist->oid == proid)
				nspname = NULL;
			else
				nspname = get_namespace_name(procform->pronamespace);

			result = quote_qualified_identifier(nspname, proname);
		}
	}
	else
	{
		/* If OID doesn't match any pg_proc entry, return it numerically */
		result = (char *) palloc(NAMEDATALEN);
		snprintf(result, NAMEDATALEN, "%u", proid);
	}

	caql_endscan(pcqCtx);

	PG_RETURN_CSTRING(result);
}
Exemplo n.º 10
0
/**
 * @brief Parse function expression
 */
ParsedFunction
ParseFunction(const char *value, bool argistype)
{
    int					i;
    ParsedFunction		ret;
    char			   *buf;
    const char		   *nextp;
    bool				done = false;
    List			   *names;
    ListCell		   *l;
    int					nargs;
    FuncCandidateList	candidates;
    FuncCandidateList	find = NULL;
    int					ncandidates = 0;
    HeapTuple			ftup;
    Form_pg_proc		pp;
    AclResult			aclresult;

    buf = palloc(strlen(value) + 1);

    /* parse function name */
    nextp = value;
    do
    {
        if (*nextp == '\"')
        {
            /* Quoted name */
            for (;;)
            {
                nextp = strchr(nextp + 1, '\"');

                /* mismatched quotes */
                if (nextp == NULL)
                    ereport(ERROR,
                            (errcode(ERRCODE_SYNTAX_ERROR),
                             errmsg("function call syntax error: %s", value)));

                if (nextp[1] != '\"')
                    break;		/* found end of quoted name */
            }

            /* nextp now points at the terminating quote */
            nextp = nextp + 1;
        }
        else if (IsIdentStart((unsigned char) *nextp))
        {
            /* Unquoted name */
            nextp++;
            while (IsIdentContent((unsigned char) *nextp))
                nextp++;
        }
        else
        {
            /* invalid syntax */
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("function call syntax error: %s", value)));
        }

        while (isspace((unsigned char) *nextp))
            nextp++;			/* skip trailing whitespace */

        if (*nextp == '.')
        {
            nextp++;
            while (isspace((unsigned char) *nextp))
                nextp++;		/* skip leading whitespace for next */
            /* we expect another name, so done remains false */
        }
        else if (*nextp == '\0' || *nextp == '(')
            done = true;
        else
        {
            /* invalid syntax */
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("function call syntax error: %s", value)));
        }

        /* Loop back if we didn't reach end of function name */
    } while (!done);

    strncpy(buf, value, nextp - value);
    buf[nextp - value] = '\0';

    names = stringToQualifiedNameList(buf);
    pfree(buf);

    if (*nextp == '\0')
    {
        if (!argistype)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("function call syntax error: %s", value)));

        nargs = -1;

        /* Get list of possible candidates from namespace search */
        candidates = FuncnameGetCandidates(names, nargs, NIL, false, false);
    }
    else
    {
        /* parse function arguments */
        nargs = 0;
        while (GetNextArgument(nextp, &ret.args[nargs], &ret.argtypes[nargs], &nextp, value, argistype))
        {
            nargs++;
            if (nargs > FUNC_MAX_ARGS)
                ereport(ERROR,
                        (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
                         errmsg("functions cannot have more than %d arguments", FUNC_MAX_ARGS)));
        }

        /* Get list of possible candidates from namespace search */
        candidates = FuncnameGetCandidates(names, nargs, NIL, true, true);
    }


    /* so now try to match up candidates */
    if (!argistype)
    {
        FuncCandidateList current_candidates;

        ncandidates = func_match_argtypes(nargs,
                                          ret.argtypes,
                                          candidates,
                                          &current_candidates);

        /* one match only? then run with it... */
        if (ncandidates == 1)
            find = current_candidates;

        /* multiple candidates? then better decide or throw an error... */
        else if (ncandidates > 1)
        {
            find = func_select_candidate(nargs, ret.argtypes,
                                         current_candidates);
        }
    }
    else if (nargs > 0)
    {
        /* Quickly check if there is an exact match to the input datatypes */
        for (find = candidates; find; find = find->next)
        {
            if (memcmp(find->args, ret.argtypes, nargs * sizeof(Oid)) == 0)
            {
                ncandidates = 1;
                break;
            }
        }
    }
    else
    {
        FuncCandidateList c;
        for (c = candidates; c; c = c->next)
            ncandidates++;
        find = candidates;
    }

    if (ncandidates == 0)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("function %s does not exist",
                        func_signature_string(names, nargs, NIL, ret.argtypes)),
                 errhint("No function matches the given name and argument types.")));

    /*
     * If we were able to choose a best candidate, we're done.
     * Otherwise, ambiguous function call.
     */
    if (ncandidates > 1 || !OidIsValid(find->oid))
        ereport(ERROR,
                (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
                 errmsg("function %s is not unique",
                        func_signature_string(names, nargs, NIL,
                                              ret.argtypes)),
                 errhint("Could not choose a best candidate function.")));

    foreach (l, names)
    {
        Value  *v = lfirst(l);

        pfree(strVal(v));
        pfree(v);
    }