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
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)