|
2 | 2 | // Licensed under the MIT License. |
3 | 3 |
|
4 | 4 | using System.Globalization; |
| 5 | +using System.Net; |
5 | 6 | using System.Text.Json; |
6 | 7 | using Azure.DataApiBuilder.Config.ObjectModel; |
7 | 8 | using Azure.DataApiBuilder.Core.Configurations; |
8 | 9 | using Azure.DataApiBuilder.Core.Models; |
9 | 10 | using Azure.DataApiBuilder.Core.Resolvers; |
10 | 11 | using Azure.DataApiBuilder.Core.Resolvers.Factories; |
| 12 | +using Azure.DataApiBuilder.Service.Exceptions; |
11 | 13 | using Azure.DataApiBuilder.Service.GraphQLBuilder; |
12 | 14 | using Azure.DataApiBuilder.Service.GraphQLBuilder.CustomScalars; |
13 | 15 | using Azure.DataApiBuilder.Service.GraphQLBuilder.GraphQLTypes; |
@@ -155,27 +157,41 @@ fieldValue.ValueKind is not (JsonValueKind.Undefined or JsonValueKind.Null)) |
155 | 157 | // transform it into the runtime type. |
156 | 158 | // We also want to ensure here that we do not unnecessarily convert values to |
157 | 159 | // strings and then force the conversion to parse them. |
158 | | - return namedType switch |
| 160 | + try |
159 | 161 | { |
160 | | - StringType => fieldValue.GetString(), // spec |
161 | | - ByteType => fieldValue.GetByte(), |
162 | | - ShortType => fieldValue.GetInt16(), |
163 | | - IntType => fieldValue.GetInt32(), // spec |
164 | | - LongType => fieldValue.GetInt64(), |
165 | | - FloatType => fieldValue.GetDouble(), // spec |
166 | | - SingleType => fieldValue.GetSingle(), |
167 | | - DecimalType => fieldValue.GetDecimal(), |
168 | | - DateTimeType => DateTimeOffset.TryParse(fieldValue.GetString()!, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTimeOffset date) ? date : null, // for DW when datetime is null it will be in "" (double quotes) due to stringagg parsing and hence we need to ensure parsing is correct. |
169 | | - DateType => DateTimeOffset.TryParse(fieldValue.GetString()!, out DateTimeOffset date) ? date : null, |
170 | | - LocalTimeType => fieldValue.GetString()!.Equals("null", StringComparison.OrdinalIgnoreCase) ? null : LocalTimePattern.ExtendedIso.Parse(fieldValue.GetString()!).Value, |
171 | | - ByteArrayType => fieldValue.GetBytesFromBase64(), |
172 | | - BooleanType => fieldValue.GetBoolean(), // spec |
173 | | - UrlType => new Uri(fieldValue.GetString()!), |
174 | | - UuidType => fieldValue.GetGuid(), |
175 | | - TimeSpanType => TimeSpan.Parse(fieldValue.GetString()!), |
176 | | - AnyType => fieldValue.ToString(), |
177 | | - _ => fieldValue.GetString() |
178 | | - }; |
| 162 | + return namedType switch |
| 163 | + { |
| 164 | + StringType => fieldValue.GetString(), // spec |
| 165 | + ByteType => fieldValue.GetByte(), |
| 166 | + ShortType => fieldValue.GetInt16(), |
| 167 | + IntType => fieldValue.GetInt32(), // spec |
| 168 | + LongType => fieldValue.GetInt64(), |
| 169 | + FloatType => fieldValue.GetDouble(), // spec |
| 170 | + SingleType => fieldValue.GetSingle(), |
| 171 | + DecimalType => fieldValue.GetDecimal(), |
| 172 | + DateTimeType => DateTimeOffset.TryParse(fieldValue.GetString()!, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTimeOffset date) ? date : null, // for DW when datetime is null it will be in "" (double quotes) due to stringagg parsing and hence we need to ensure parsing is correct. |
| 173 | + DateType => DateTimeOffset.TryParse(fieldValue.GetString()!, out DateTimeOffset date) ? date : null, |
| 174 | + LocalTimeType => fieldValue.GetString()!.Equals("null", StringComparison.OrdinalIgnoreCase) ? null : LocalTimePattern.ExtendedIso.Parse(fieldValue.GetString()!).Value, |
| 175 | + ByteArrayType => fieldValue.GetBytesFromBase64(), |
| 176 | + BooleanType => fieldValue.GetBoolean(), // spec |
| 177 | + UrlType => new Uri(fieldValue.GetString()!), |
| 178 | + UuidType => fieldValue.GetGuid(), |
| 179 | + TimeSpanType => TimeSpan.Parse(fieldValue.GetString()!), |
| 180 | + AnyType => fieldValue.ToString(), |
| 181 | + _ => fieldValue.GetString() |
| 182 | + }; |
| 183 | + } |
| 184 | + catch (Exception ex) when (ex is InvalidOperationException or FormatException) |
| 185 | + { |
| 186 | + // this usually means that database column type was changed since generating the GraphQL schema |
| 187 | + // for e.g. System.FormatException - One of the identified items was in an invalid format |
| 188 | + // System.InvalidOperationException - The requested operation requires an element of type 'Number', but the target element has type 'String'. |
| 189 | + throw new DataApiBuilderException( |
| 190 | + message: $"The {context.Selection.Field.Name} value could not be parsed for configured GraphQL data type {namedType.Name}", |
| 191 | + statusCode: HttpStatusCode.Conflict, |
| 192 | + subStatusCode: DataApiBuilderException.SubStatusCodes.GraphQLMapping, |
| 193 | + ex); |
| 194 | + } |
179 | 195 | } |
180 | 196 |
|
181 | 197 | return null; |
|
0 commit comments