Exemple #1
0
        for nested in nested_path_ids:
            tuple_path_ids.extend(nested)
    else:
        tuple_path_ids = []

    fcall = irast.FunctionCall(
        args=final_args,
        func_shortname=func_name,
        backend_name=func.get_backend_name(env.schema),
        func_polymorphic=is_polymorphic,
        func_sql_function=func.get_from_function(env.schema),
        force_return_cast=func.get_force_return_cast(env.schema),
        volatility=func.get_volatility(env.schema),
        sql_func_has_out_params=func.get_sql_func_has_out_params(env.schema),
        error_on_null_result=func.get_error_on_null_result(env.schema),
        params_typemods=params_typemods,
        context=expr.context,
        typeref=typegen.type_to_typeref(
            rtype, env=env,
        ),
        typemod=matched_call.func.get_return_typemod(env.schema),
        has_empty_variadic=matched_call.has_empty_variadic,
        variadic_param_type=variadic_param_type,
        func_initial_value=func_initial_value,
        tuple_path_ids=tuple_path_ids,
    )

    return setgen.ensure_set(fcall, typehint=rtype, path_id=path_id, ctx=ctx)


#: A dictionary of conditional callables and the indices
Exemple #2
0
def compile_FunctionCall(expr: qlast.FunctionCall, *,
                         ctx: context.ContextLevel) -> irast.Base:

    env = ctx.env

    if isinstance(expr.func, str):
        if (ctx.env.func_params is not None
                and ctx.env.func_params.get_by_name(env.schema, expr.func)):
            raise errors.QueryError(f'parameter `{expr.func}` is not callable',
                                    context=expr.context)

        funcname = expr.func
    else:
        funcname = sn.Name(expr.func[1], expr.func[0])

    funcs = env.schema.get_functions(funcname, module_aliases=ctx.modaliases)

    if funcs is None:
        raise errors.QueryError(f'could not resolve function name {funcname}',
                                context=expr.context)

    in_polymorphic_func = (ctx.env.func_params is not None
                           and ctx.env.func_params.has_polymorphic(env.schema))

    in_abstract_constraint = (
        in_polymorphic_func
        and ctx.env.parent_object_type is s_constr.Constraint)

    args, kwargs = compile_call_args(expr, funcname, ctx=ctx)
    matched = polyres.find_callable(funcs, args=args, kwargs=kwargs, ctx=ctx)
    if not matched:
        raise errors.QueryError(
            f'could not find a function variant {funcname}',
            context=expr.context)
    elif len(matched) > 1:
        if in_abstract_constraint:
            matched_call = matched[0]
        else:
            raise errors.QueryError(f'function {funcname} is not unique',
                                    context=expr.context)
    else:
        matched_call = matched[0]

    func = matched_call.func
    assert isinstance(func, s_func.Function)
    func_name = func.get_shortname(env.schema)

    if not ctx.env.session_mode and func.get_session_only(env.schema):
        raise errors.QueryError(
            f'{func_name}() cannot be called in a non-session context',
            context=expr.context)

    final_args, params_typemods = finalize_args(matched_call, ctx=ctx)

    matched_func_params = func.get_params(env.schema)
    variadic_param = matched_func_params.find_variadic(env.schema)
    variadic_param_type = None
    if variadic_param is not None:
        variadic_param_type = irtyputils.type_to_typeref(
            env.schema, variadic_param.get_type(env.schema))

    matched_func_ret_type = func.get_return_type(env.schema)
    is_polymorphic = (any(
        p.get_type(env.schema).is_polymorphic(env.schema)
        for p in matched_func_params.objects(env.schema))
                      and matched_func_ret_type.is_polymorphic(env.schema))

    matched_func_initial_value = func.get_initial_value(env.schema)

    if not in_abstract_constraint:
        # We cannot add strong references to functions from
        # abstract constraints, since we cannot know which
        # form of the function is actually used.
        env.schema_refs.add(func)

    func_initial_value: typing.Optional[irast.Set]

    if matched_func_initial_value is not None:
        iv_ql = qlast.TypeCast(
            expr=qlparser.parse_fragment(matched_func_initial_value.text),
            type=typegen.type_to_ql_typeref(matched_call.return_type, ctx=ctx),
        )
        func_initial_value = setgen.ensure_set(
            dispatch.compile(iv_ql, ctx=ctx),
            ctx=ctx,
        )
    else:
        func_initial_value = None

    rtype = matched_call.return_type
    path_id = pathctx.get_expression_path_id(rtype, ctx=ctx)

    if rtype.is_tuple():
        rtype = typing.cast(s_types.Tuple, rtype)
        tuple_path_ids = []
        nested_path_ids = []
        for n, st in rtype.iter_subtypes(ctx.env.schema):
            elem_path_id = pathctx.get_tuple_indirection_path_id(
                path_id, n, st, ctx=ctx).strip_weak_namespaces()

            if st.is_tuple():
                nested_path_ids.append([
                    pathctx.get_tuple_indirection_path_id(
                        elem_path_id, nn, sst,
                        ctx=ctx).strip_weak_namespaces()
                    for nn, sst in st.iter_subtypes(ctx.env.schema)
                ])

            tuple_path_ids.append(elem_path_id)
        for nested in nested_path_ids:
            tuple_path_ids.extend(nested)
    else:
        tuple_path_ids = []

    fcall = irast.FunctionCall(
        args=final_args,
        func_module_id=env.schema.get_global(s_mod.Module,
                                             func_name.module).id,
        func_shortname=func_name,
        func_polymorphic=is_polymorphic,
        func_sql_function=func.get_from_function(env.schema),
        force_return_cast=func.get_force_return_cast(env.schema),
        session_only=func.get_session_only(env.schema),
        volatility=func.get_volatility(env.schema),
        sql_func_has_out_params=func.get_sql_func_has_out_params(env.schema),
        error_on_null_result=func.get_error_on_null_result(env.schema),
        params_typemods=params_typemods,
        context=expr.context,
        typeref=irtyputils.type_to_typeref(env.schema, rtype),
        typemod=matched_call.func.get_return_typemod(env.schema),
        has_empty_variadic=matched_call.has_empty_variadic,
        variadic_param_type=variadic_param_type,
        func_initial_value=func_initial_value,
        tuple_path_ids=tuple_path_ids,
    )

    return setgen.ensure_set(fcall, typehint=rtype, path_id=path_id, ctx=ctx)
def compile_FunctionCall(
        expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Base:

    env = ctx.env

    if isinstance(expr.func, str):
        if ctx.func is not None:
            ctx_func_params = ctx.func.get_params(env.schema)
            if ctx_func_params.get_by_name(env.schema, expr.func):
                raise errors.QueryError(
                    f'parameter `{expr.func}` is not callable',
                    context=expr.context)

        funcname = expr.func
    else:
        funcname = sn.Name(expr.func[1], expr.func[0])

    funcs = env.schema.get_functions(funcname, module_aliases=ctx.modaliases)

    if funcs is None:
        raise errors.QueryError(
            f'could not resolve function name {funcname}',
            context=expr.context)

    args, kwargs = compile_call_args(expr, funcname, ctx=ctx)
    matched = polyres.find_callable(funcs, args=args, kwargs=kwargs, ctx=ctx)
    if not matched:
        raise errors.QueryError(
            f'could not find a function variant {funcname}',
            context=expr.context)
    elif len(matched) > 1:
        raise errors.QueryError(
            f'function {funcname} is not unique',
            context=expr.context)
    else:
        matched_call = matched[0]

    args, params_typemods = finalize_args(matched_call, ctx=ctx)

    matched_func_params = matched_call.func.get_params(env.schema)
    variadic_param = matched_func_params.find_variadic(env.schema)
    variadic_param_type = None
    if variadic_param is not None:
        variadic_param_type = irtyputils.type_to_typeref(
            env.schema,
            variadic_param.get_type(env.schema))

    matched_func_ret_type = matched_call.func.get_return_type(env.schema)
    is_polymorphic = (
        any(p.get_type(env.schema).is_polymorphic(env.schema)
            for p in matched_func_params.objects(env.schema)) and
        matched_func_ret_type.is_polymorphic(env.schema)
    )

    matched_func_initial_value = matched_call.func.get_initial_value(
        env.schema)

    func = matched_call.func
    func_name = func.get_shortname(env.schema)

    if matched_func_initial_value is not None:
        iv_ql = qlast.TypeCast(
            expr=qlparser.parse_fragment(matched_func_initial_value.text),
            type=typegen.type_to_ql_typeref(matched_call.return_type, ctx=ctx),
        )
        func_initial_value = dispatch.compile(iv_ql, ctx=ctx)
    else:
        func_initial_value = None

    rtype = matched_call.return_type
    path_id = pathctx.get_expression_path_id(rtype, ctx=ctx)

    if rtype.is_tuple():
        tuple_path_ids = []
        nested_path_ids = []
        for n, st in rtype.iter_subtypes(ctx.env.schema):
            elem_path_id = pathctx.get_tuple_indirection_path_id(
                path_id, n, st, ctx=ctx).strip_weak_namespaces()

            if st.is_tuple():
                nested_path_ids.append([
                    pathctx.get_tuple_indirection_path_id(
                        elem_path_id, nn, sst, ctx=ctx).strip_weak_namespaces()
                    for nn, sst in st.iter_subtypes(ctx.env.schema)
                ])

            tuple_path_ids.append(elem_path_id)
        for nested in nested_path_ids:
            tuple_path_ids.extend(nested)
    else:
        tuple_path_ids = None

    fcall = irast.FunctionCall(
        args=args,
        func_module_id=env.schema.get_global(
            s_mod.Module, func_name.module).id,
        func_shortname=func_name,
        func_polymorphic=is_polymorphic,
        func_sql_function=func.get_from_function(env.schema),
        force_return_cast=func.get_force_return_cast(env.schema),
        sql_func_has_out_params=func.get_sql_func_has_out_params(env.schema),
        error_on_null_result=func.get_error_on_null_result(env.schema),
        params_typemods=params_typemods,
        context=expr.context,
        typeref=irtyputils.type_to_typeref(env.schema, rtype),
        typemod=matched_call.func.get_return_typemod(env.schema),
        has_empty_variadic=matched_call.has_empty_variadic,
        variadic_param_type=variadic_param_type,
        func_initial_value=func_initial_value,
        tuple_path_ids=tuple_path_ids,
    )

    return setgen.ensure_set(fcall, typehint=rtype, path_id=path_id, ctx=ctx)