示例#1
0
 private bool TryGetRoutineMapping(PgRoutineGroup r, out string value)
 {
     if (settings.Mapping.TryGetValue(r.TypeUdtName, out value))
     {
         return(true);
     }
     return(settings.Mapping.TryGetValue(r.DataType, out value));
 }
示例#2
0
 private List <Param> GetParamsInfo(PgRoutineGroup routine)
 {
     return(routine.Parameters.Select(p => new Param(settings)
     {
         PgName = p.Name,
         PgType = p.DataType,
         Type = GetParamType(p),
         DbType = GetParamDbType(p)
     }).ToList());
 }
示例#3
0
        private void PrepareParams(PgRoutineGroup routine)
        {
            var i = 0;

            foreach (var p in routine.Parameters)
            {
                if (p.Name == null)
                {
                    p.Name = $"param{++i}";
                }
            }
        }
示例#4
0
 private string GetReturnMethod(PgRoutineGroup routine, string name)
 {
     if (settings.RoutinesReturnMethods.TryGetValue(routine.RoutineName, out var result))
     {
         return(string.IsNullOrEmpty(result) ? null : result);
     }
     if (settings.RoutinesReturnMethods.TryGetValue(name, out result))
     {
         return(string.IsNullOrEmpty(result) ? null : result);
     }
     return(settings.ReturnMethod);
 }
示例#5
0
        private string BuildRecordModel(PgRoutineGroup routine)
        {
            var suffix = ++recordModelCount == 1 ? "" : recordModelCount.ToString();
            var name   = $"{this.Name.ToUpperCamelCase()}{suffix}Result";

            if (settings.Mapping.TryGetValue(name, out var custom))
            {
                recordModelCount--;
                return(custom);
            }
            if (settings.CustomModels.ContainsKey(name))
            {
                name = settings.CustomModels[name];
            }
            else if (settings.CustomModels.ContainsKey(routine.TypeUdtName))
            {
                name = settings.CustomModels[routine.TypeUdtName];
            }
            return(BuildModel(name, connection => connection.GetRoutineReturnsRecord(routine)));
        }
示例#6
0
        private string BuildUserDefinedModel(PgRoutineGroup routine)
        {
            var name = routine.TypeUdtName.ToUpperCamelCase();

            if (settings.Mapping.TryGetValue(name, out var custom))
            {
                return(custom);
            }
            if (settings.CustomModels.ContainsKey(name))
            {
                name = settings.CustomModels[name];
            }
            else if (settings.CustomModels.ContainsKey(routine.TypeUdtName))
            {
                name = settings.CustomModels[routine.TypeUdtName];
            }
            BuildModel(name, connection => connection.GetRoutineReturnsTable(routine));
            UserDefinedModels.Add(name);
            return(name);
        }
示例#7
0
 private Return GetReturnInfo(PgRoutineGroup routine)
 {
     if (routine == null || routine.DataType == null || routine.DataType == "void")
     {
         return(new Return {
             PgName = "void", Name = "void", IsVoid = true, IsEnumerable = false
         });
     }
     if (TryGetRoutineMapping(routine, out var result))
     {
         if (routine.DataType == "ARRAY")
         {
             return(new Return {
                 PgName = $"{routine.TypeUdtName}[]", Name = $"{result}[]", IsVoid = false, IsEnumerable = false
             });
         }
         if (result != "string")
         {
             return(new Return {
                 PgName = routine.DataType, Name = $"{result}?", IsVoid = false, IsEnumerable = false
             });
         }
         return(new Return {
             PgName = routine.DataType, Name = result, IsVoid = false, IsEnumerable = false
         });
     }
     if (routine.DataType == "USER-DEFINED")
     {
         return(new Return {
             PgName = routine.TypeUdtName, Name = BuildUserDefinedModel(routine), IsVoid = false, IsEnumerable = true
         });
     }
     if (routine.DataType == "record")
     {
         return(new Return {
             PgName = routine.TypeUdtName, Name = BuildRecordModel(routine), IsVoid = false, IsEnumerable = true
         });
     }
     throw new ArgumentException($"Could not find mapping \"{routine.DataType}\" for return type of routine \"{routine.RoutineName}\"");
 }
示例#8
0
 private void BuildCommentHeader(PgRoutineGroup routine, Return @return, List <Param> @params, bool sync, string returnMethod)
 {
     Class.AppendLine($"{I2}/// <summary>");
     Class.AppendLine($"{I2}/// {(sync ? "Executes" : "Asynchronously executes")} {routine.Language} {routine.RoutineType} \"{Name}\"");
     if (!string.IsNullOrEmpty(routine.Description))
     {
         var description = routine.Description.Replace("\r\n", "\n").Trim('\n');
         Class.Append(I2);
         Class.AppendLine(string.Join($"{Environment.NewLine}{I2}",
                                      description.Split("\n").Select(d => $"/// {d}")));
     }
     Class.AppendLine($"{I2}/// </summary>");
     foreach (var p in @params)
     {
         Class.AppendLine($"{I2}/// <param name=\"{p.Name}\">{p.PgName} {p.PgType}</param>");
     }
     if (@return.IsEnumerable || returnMethod == null)
     {
         if (sync)
         {
             Class.AppendLine($"{I2}/// <returns>IEnumerable of {@return.Name} instances</returns>");
         }
         else
         {
             Class.AppendLine($"{I2}/// <returns>IAsyncEnumerable of {@return.Name} instances</returns>");
         }
     }
     else
     {
         if (sync)
         {
             Class.AppendLine($"{I2}/// <returns>{@return.Name}</returns>");
         }
         else
         {
             Class.AppendLine($"{I2}/// <returns>ValueTask whose Result property is {@return.Name}</returns>");
         }
     }
 }
示例#9
0
        private void BuildSyncMethod(PgRoutineGroup routine, Return @return, List <Param> @params)
        {
            var name         = routine.RoutineName.ToUpperCamelCase();
            var returnMethod = GetReturnMethod(routine, name);

            Class.AppendLine();
            BuildCommentHeader(routine, @return, @params, true, returnMethod);
            var actualReturns = @return.IsEnumerable ? $"IEnumerable<{@return.Name}>" : (returnMethod == null ? $"IEnumerable<{@return.Name}>" : @return.Name);

            void AddMethod() => Methods.Add(new Method
            {
                Name          = name,
                Namespace     = @namespace,
                Params        = @params,
                Returns       = @return,
                ActualReturns = actualReturns,
                Sync          = true
            });

            void AddBodyCode(string bodyTab, string paramsTab)
            {
                Class.AppendLine($"{bodyTab}.AsProcedure()");
                if (@return.IsVoid)
                {
                    Class.Append($"{bodyTab}.Execute(Name");
                    if (@params.Count == 0)
                    {
                        Class.AppendLine(");");
                        AddMethod();
                        return;
                    }
                    else
                    {
                        Class.AppendLine(",");
                    }
                }
                else
                {
                    Class.Append($"{bodyTab}.Read<{@return.Name}>(Name");
                    if (@params.Count > 0)
                    {
                        Class.AppendLine(",");
                    }
                }
                BuildParams(@params, paramsTab);
                if (@return.IsVoid || @return.IsEnumerable || returnMethod == null)
                {
                    Class.AppendLine(");");
                    return;
                }
                Class.AppendLine(")");
                Class.AppendLine($"{bodyTab}.{returnMethod}();");
            }

            if (settings.UseExpressionBody)
            {
                Class.Append($"{I2}public static {actualReturns} {name}(this NpgsqlConnection connection");
                BuildMethodParams(@params);
                Class.AppendLine(") => connection");
                AddBodyCode(I3, I4);
            }
            else
            {
                Class.Append($"{I2}public static {actualReturns} {name}(this NpgsqlConnection connection");
                BuildMethodParams(@params);
                Class.AppendLine(")");
                Class.AppendLine($"{I2}{{");
                if (@return.IsVoid)
                {
                    Class.AppendLine($"{I3}connection");
                }
                else
                {
                    Class.AppendLine($"{I3}return connection");
                }
                AddBodyCode(I4, I5);
                Class.AppendLine($"{I2}}}");
            }
            AddMethod();
        }
示例#10
0
        public static IEnumerable <PgReturns> GetRoutineReturnsRecord(this NpgsqlConnection connection, PgRoutineGroup routine) =>
        connection.Read <PgReturns>(@"

            select 
                p.ordinal_position as ordinal,
                p.parameter_name as name,
                regexp_replace(p.udt_name, '^[_]', '') as type,
                p.data_type,
                p.data_type = 'ARRAY' as array,
                true as nullable
            from 
                information_schema.parameters p
            where 
                p.ordinal_position is not null 
                and (p.parameter_mode = 'OUT' or p.parameter_mode = 'INOUT')
                and p.specific_name = @specificName and p.specific_schema = @specificSchema
            order by 
                p.ordinal_position 

            ",
                                    ("specificName", routine.SpecificName, DbType.AnsiString),
                                    ("specificSchema", routine.SpecificSchema, DbType.AnsiString));
示例#11
0
        private static IEnumerable <PgReturns> GetTypeColumnsForRoutine(this NpgsqlConnection connection, PgRoutineGroup routine) =>
        connection.Read <PgReturns>(@"

            select 
                (row_number() over ())::int as ordinal,
                a.attname as name, 
                regexp_replace(t.typname, '^[_]', '') as type, 
                null as data_type,
                t.typinput::text like 'array_%' as array, 
                not t.typnotnull as nullable

            from pg_class c 
            inner join pg_attribute a on c.oid = a.attrelid 
            inner join pg_type t on a.atttypid = t.oid
            where 
                c.relname = @typeUdtName

            ",
                                    ("typeUdtName", routine.TypeUdtName, DbType.AnsiString));
示例#12
0
        private static IEnumerable <PgReturns> GetTableColumnsForRoutine(this NpgsqlConnection connection, PgRoutineGroup routine) =>
        connection.Read <PgReturns>(@"

            select 
                c.ordinal_position as ordinal,
                c.column_name as name, 
                regexp_replace(c.udt_name, '^[_]', '') as type,
                c.data_type,
                c.data_type = 'ARRAY' as array,
                c.is_nullable = 'YES' as nullable

            from
                information_schema.columns c
            where
                c.table_name = @typeUdtName
            order by
                c.ordinal_position

            ",
                                    ("typeUdtName", routine.TypeUdtName, DbType.AnsiString));
示例#13
0
        public static IEnumerable <PgReturns> GetRoutineReturnsTable(this NpgsqlConnection connection, PgRoutineGroup routine)
        {
            var result = connection.GetTableColumnsForRoutine(routine);

            if (result.Any())
            {
                return(result);
            }
            return(connection.GetTypeColumnsForRoutine(routine));
        }