/// <summary> /// Generates aggregate function model from schema data. /// </summary> /// <param name="dataContext">Data context model.</param> /// <param name="func">Function schema.</param> /// <param name="defaultSchemas">List of default database schema names.</param> private void BuildAggregateFunction(DataContextModel dataContext, AggregateFunction func, ISet <string> defaultSchemas) { var(name, isNonDefaultSchema) = ProcessObjectName(func.Name, defaultSchemas); var method = new MethodModel( _namingServices.NormalizeIdentifier(_options.DataModel.ProcedureNameOptions, (func.Name.Package != null ? $"{func.Name.Package}_" : null) + name.Name)) { Modifiers = Modifiers.Public | Modifiers.Static | Modifiers.Extension, Summary = func.Description, }; var metadata = new FunctionMetadata() { Name = name, ServerSideOnly = true, IsAggregate = true }; if (func.Parameters.Count > 0) { metadata.ArgIndices = new int[func.Parameters.Count]; for (var i = 0; i < metadata.ArgIndices.Length; i++) { metadata.ArgIndices[i] = i + 1; } } // just a guard if (func.Result is not ScalarResult scalarResult) { throw new InvalidOperationException($"Aggregate function {func.Name} returns non-scalar value."); } var typeMapping = MapType(scalarResult.Type); var funcModel = new AggregateFunctionModel(name, method, metadata, typeMapping.CLRType.WithNullability(scalarResult.Nullable)); BuildParameters(func.Parameters, funcModel.Parameters); _interceptors.PreprocessAggregateFunction(_languageProvider.TypeParser, funcModel); if (isNonDefaultSchema && _options.DataModel.GenerateSchemaAsType) { GetOrAddAdditionalSchema(dataContext, func.Name.Schema !).AggregateFunctions.Add(funcModel); } else { dataContext.AggregateFunctions.Add(funcModel); } }
/// <summary> /// Using this method user could modify aggregate function code generation options: /// <list type="bullet"> /// <item>Return type: <see cref="AggregateFunctionModel.ReturnType"/></item> /// <item>Function metadata: <see cref="ScalarFunctionModelBase.Metadata"/></item> /// <item>Method code-generation options: <see cref="FunctionModelBase.Method"/></item> /// <item>Parameters: <see cref="FunctionModelBase.Parameters"/></item> /// </list> /// </summary> /// <param name="typeParser">Type parser service to create type tokens.</param> /// <param name="functionModel">Function model descriptor.</param> public virtual void PreprocessAggregateFunction(ITypeParser typeParser, AggregateFunctionModel functionModel) { }