Пример #1
0
 /// <summary>
 /// Using this method user could modify scalar function code generation options:
 /// <list type="bullet">
 /// <item>Return scalar value or tuple descriptor: <see cref="ScalarFunctionModel.Return"/> or <see cref="ScalarFunctionModel.ReturnTuple"/></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 PreprocessScalarFunction(ITypeParser typeParser, ScalarFunctionModel functionModel)
 {
 }
Пример #2
0
        /// <summary>
        /// Generates scalar 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 BuildScalarFunction(DataContextModel dataContext, ScalarFunction 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,
                Summary   = func.Description
            };

            var metadata = new FunctionMetadata()
            {
                Name           = name,
                ServerSideOnly = true
            };

            var funcModel = new ScalarFunctionModel(name, method, metadata);

            BuildParameters(func.Parameters, funcModel.Parameters);

            // thanks to pgsql, scalar function could return not only scalar, but also tuple or just nothing
            switch (func.Result.Kind)
            {
            case ResultKind.Scalar:
            {
                var scalarResult = (ScalarResult)func.Result;
                var typeMapping  = MapType(scalarResult.Type);
                funcModel.Return = typeMapping.CLRType.WithNullability(scalarResult.Nullable);
                // TODO: DataType not used by current scalar function mapping API
                break;
            }

            case ResultKind.Tuple:
            {
                var tupleResult = (TupleResult)func.Result;

                // tuple model class
                var @class = new ClassModel(
                    _namingServices.NormalizeIdentifier(
                        _options.DataModel.FunctionTupleResultClassNameOptions,
                        func.Name.Name))
                {
                    Modifiers = Modifiers.Public | Modifiers.Partial
                };
                funcModel.ReturnTuple = new TupleModel(@class)
                {
                    CanBeNull = tupleResult.Nullable
                };

                // fields order must be preserved, as tuple fields mapped by ordinal
                foreach (var field in tupleResult.Fields)
                {
                    var typeMapping = MapType(field.Type);

                    var prop = new PropertyModel(_namingServices.NormalizeIdentifier(_options.DataModel.FunctionTupleResultPropertyNameOptions, field.Name ?? "Field"), typeMapping.CLRType.WithNullability(field.Nullable))
                    {
                        Modifiers = Modifiers.Public,
                        IsDefault = true,
                        HasSetter = true
                    };
                    funcModel.ReturnTuple.Fields.Add(new TupleFieldModel(prop, field.Type)
                        {
                            DataType = typeMapping.DataType
                        });
                }
                break;
            }

            case ResultKind.Void:
                // just regular postgresql void function, nothing to see here...
                // because function must have return type to be callable in query, we set return type to object?
                funcModel.Return = WellKnownTypes.System.ObjectNullable;
                break;
            }

            _interceptors.PreprocessScalarFunction(_languageProvider.TypeParser, funcModel);

            if (isNonDefaultSchema && _options.DataModel.GenerateSchemaAsType)
            {
                GetOrAddAdditionalSchema(dataContext, func.Name.Schema !).ScalarFunctions.Add(funcModel);
            }
            else
            {
                dataContext.ScalarFunctions.Add(funcModel);
            }
        }