Exemplo n.º 1
0
/*
 * Return permissive policies to be added
 */
List *
test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
{
	List	   *policies = NIL;
	RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
	Datum		role;
	FuncCall   *n;
	Node	   *e;
	ColumnRef  *c;
	ParseState *qual_pstate;
	RangeTblEntry *rte;

	if (strcmp(RelationGetRelationName(relation), "rls_test_permissive")
		&& strcmp(RelationGetRelationName(relation), "rls_test_both"))
		return NIL;

	qual_pstate = make_parsestate(NULL);

	rte = addRangeTableEntryForRelation(qual_pstate, relation, NULL, false,
										false);
	addRTEtoQuery(qual_pstate, rte, false, true, true);

	role = ObjectIdGetDatum(ACL_ID_PUBLIC);

	policy->policy_name = pstrdup("extension policy");
	policy->policy_id = InvalidOid;
	policy->polcmd = '*';
	policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, 'i');

	/*
	 * policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid,
	 * sizeof(bool), BoolGetDatum(true), false, true);
	 */

	n = makeFuncCall(list_make2(makeString("pg_catalog"),
								makeString("current_user")), NIL, 0);

	c = makeNode(ColumnRef);
	c->fields = list_make1(makeString("username"));
	c->location = 0;

	e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);

	policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
												 EXPR_KIND_POLICY,
												 "POLICY");

	policy->with_check_qual = copyObject(policy->qual);
	policy->hassublinks = false;

	policies = list_make1(policy);

	return policies;
}
Exemplo n.º 2
0
/*
 * Interpret the function parameter list of a CREATE FUNCTION or
 * CREATE AGGREGATE statement.
 *
 * Input parameters:
 * parameters: list of FunctionParameter structs
 * languageOid: OID of function language (InvalidOid if it's CREATE AGGREGATE)
 * is_aggregate: needed only to determine error handling
 * queryString: likewise, needed only for error handling
 *
 * Results are stored into output parameters.  parameterTypes must always
 * be created, but the other arrays are set to NULL if not needed.
 * variadicArgType is set to the variadic array type if there's a VARIADIC
 * parameter (there can be only one); or to InvalidOid if not.
 * requiredResultType is set to InvalidOid if there are no OUT parameters,
 * else it is set to the OID of the implied result type.
 */
void
interpret_function_parameter_list(List *parameters,
								  Oid languageOid,
								  bool is_aggregate,
								  const char *queryString,
								  oidvector **parameterTypes,
								  ArrayType **allParameterTypes,
								  ArrayType **parameterModes,
								  ArrayType **parameterNames,
								  List **parameterDefaults,
								  Oid *variadicArgType,
								  Oid *requiredResultType)
{
	int			parameterCount = list_length(parameters);
	Oid		   *inTypes;
	int			inCount = 0;
	Datum	   *allTypes;
	Datum	   *paramModes;
	Datum	   *paramNames;
	int			outCount = 0;
	int			varCount = 0;
	bool		have_names = false;
	bool		have_defaults = false;
	ListCell   *x;
	int			i;
	ParseState *pstate;

	*variadicArgType = InvalidOid;		/* default result */
	*requiredResultType = InvalidOid;	/* default result */

	inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
	allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
	paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
	paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
	*parameterDefaults = NIL;

	/* may need a pstate for parse analysis of default exprs */
	pstate = make_parsestate(NULL);
	pstate->p_sourcetext = queryString;

	/* Scan the list and extract data into work arrays */
	i = 0;
	foreach(x, parameters)
	{
		FunctionParameter *fp = (FunctionParameter *) lfirst(x);
		TypeName   *t = fp->argType;
		bool		isinput = false;
		Oid			toid;
		Type		typtup;
		AclResult	aclresult;

		typtup = LookupTypeName(NULL, t, NULL, false);
		if (typtup)
		{
			if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
			{
				/* As above, hard error if language is SQL */
				if (languageOid == SQLlanguageId)
					ereport(ERROR,
							(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
						   errmsg("SQL function cannot accept shell type %s",
								  TypeNameToString(t))));
				/* We don't allow creating aggregates on shell types either */
				else if (is_aggregate)
					ereport(ERROR,
							(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
							 errmsg("aggregate cannot accept shell type %s",
									TypeNameToString(t))));
				else
					ereport(NOTICE,
							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
							 errmsg("argument type %s is only a shell",
									TypeNameToString(t))));
			}
			toid = typeTypeId(typtup);
			ReleaseSysCache(typtup);
		}
		else
		{
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
					 errmsg("type %s does not exist",
							TypeNameToString(t))));
			toid = InvalidOid;	/* keep compiler quiet */
		}

		aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);
		if (aclresult != ACLCHECK_OK)
			aclcheck_error_type(aclresult, toid);

		if (t->setof)
		{
			if (is_aggregate)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
						 errmsg("aggregates cannot accept set arguments")));
			else
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
						 errmsg("functions cannot accept set arguments")));
		}

		/* handle input parameters */
		if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
		{
			/* other input parameters can't follow a VARIADIC parameter */
			if (varCount > 0)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
						 errmsg("VARIADIC parameter must be the last input parameter")));
			inTypes[inCount++] = toid;
			isinput = true;
		}

		/* handle output parameters */
		if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
		{
			if (outCount == 0)	/* save first output param's type */
				*requiredResultType = toid;
			outCount++;
		}

		if (fp->mode == FUNC_PARAM_VARIADIC)
		{
			*variadicArgType = toid;
			varCount++;
			/* validate variadic parameter type */
			switch (toid)
			{
				case ANYARRAYOID:
				case ANYOID:
					/* okay */
					break;
				default:
					if (!OidIsValid(get_element_type(toid)))
						ereport(ERROR,
								(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
							 errmsg("VARIADIC parameter must be an array")));
					break;
			}
		}

		allTypes[i] = ObjectIdGetDatum(toid);

		paramModes[i] = CharGetDatum(fp->mode);

		if (fp->name && fp->name[0])
		{
			ListCell   *px;

			/*
			 * As of Postgres 9.0 we disallow using the same name for two
			 * input or two output function parameters.  Depending on the
			 * function's language, conflicting input and output names might
			 * be bad too, but we leave it to the PL to complain if so.
			 */
			foreach(px, parameters)
			{
				FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);

				if (prevfp == fp)
					break;
				/* pure in doesn't conflict with pure out */
				if ((fp->mode == FUNC_PARAM_IN ||
					 fp->mode == FUNC_PARAM_VARIADIC) &&
					(prevfp->mode == FUNC_PARAM_OUT ||
					 prevfp->mode == FUNC_PARAM_TABLE))
					continue;
				if ((prevfp->mode == FUNC_PARAM_IN ||
					 prevfp->mode == FUNC_PARAM_VARIADIC) &&
					(fp->mode == FUNC_PARAM_OUT ||
					 fp->mode == FUNC_PARAM_TABLE))
					continue;
				if (prevfp->name && prevfp->name[0] &&
					strcmp(prevfp->name, fp->name) == 0)
					ereport(ERROR,
							(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
						  errmsg("parameter name \"%s\" used more than once",
								 fp->name)));
			}
Exemplo n.º 3
0
/*
 * GetStreamScanPlan
 */
ForeignScan *
GetStreamScanPlan(PlannerInfo *root, RelOptInfo *baserel,
                  Oid relid, ForeignPath *best_path, List *tlist, List *scan_clauses, Plan *outer_plan)
{
    StreamFdwInfo *sinfo = (StreamFdwInfo *) baserel->fdw_private;
    List *physical_tlist = build_physical_tlist(root, baserel);
    RangeTblEntry *rte = NULL;
    int i;
    TableSampleClause *sample;
    Value *sample_cutoff = NULL;

    /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    scan_clauses = extract_actual_clauses(scan_clauses, false);

    for (i = 1; i <= root->simple_rel_array_size; i++)
    {
        rte = root->simple_rte_array[i];
        if (rte && rte->relid == relid)
            break;
    }

    if (!rte || rte->relid != relid)
        elog(ERROR, "stream RTE missing");

    sample = rte->tablesample;
    if (sample)
    {
        double dcutoff;
        Datum d;
        ExprContext *econtext;
        bool isnull;
        Node *node;
        Expr *expr;
        ExprState *estate;
        ParseState *ps = make_parsestate(NULL);
        float4 percent;

        if (sample->tsmhandler != BERNOULLI_OID)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("tablesample method %s is not supported by streams", get_func_name(sample->tsmhandler)),
                     errhint("Only bernoulli tablesample method can be used with streams.")));

        if (sample->repeatable)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("streams don't support the REPEATABLE clause for tablesample")));

        econtext = CreateStandaloneExprContext();

        ps = make_parsestate(NULL);
        node = (Node *) linitial(sample->args);
        node = transformExpr(ps, node, EXPR_KIND_OTHER);
        expr = expression_planner((Expr *) node);

        estate = ExecInitExpr(expr, NULL);
        d = ExecEvalExpr(estate, econtext, &isnull, NULL);

        free_parsestate(ps);
        FreeExprContext(econtext, false);

        percent = DatumGetFloat4(d);
        if (percent < 0 || percent > 100 || isnan(percent))
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
                     errmsg("sample percentage must be between 0 and 100")));

        dcutoff = rint(((double) RAND_MAX + 1) * percent / 100);
        sample_cutoff = makeInteger((int) dcutoff);
    }

    return make_foreignscan(tlist, scan_clauses, baserel->relid,
                            NIL, list_make3(sinfo->colnames, physical_tlist, sample_cutoff), NIL, NIL, outer_plan);
}