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)); }
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()); }
private void PrepareParams(PgRoutineGroup routine) { var i = 0; foreach (var p in routine.Parameters) { if (p.Name == null) { p.Name = $"param{++i}"; } } }
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); }
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))); }
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); }
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}\""); }
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>"); } } }
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(); }
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));
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));
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));
public static IEnumerable <PgReturns> GetRoutineReturnsTable(this NpgsqlConnection connection, PgRoutineGroup routine) { var result = connection.GetTableColumnsForRoutine(routine); if (result.Any()) { return(result); } return(connection.GetTypeColumnsForRoutine(routine)); }