public SqlExpression TranslateArrayLength(SqlExpression expression) { if (expression is ColumnExpression columnExpression && columnExpression.TypeMapping is NpgsqlJsonTypeMapping mapping) { return(_sqlExpressionFactory.Function( mapping.IsJsonb ? "jsonb_array_length" : "json_array_length", new[] { expression }, typeof(int))); } if (expression is JsonTraversalExpression traversal) { // The traversal expression has ReturnsText=true (e.g. ->> not ->), so we recreate it to return // the JSON object instead. var lastPathComponent = traversal.Path.Last(); var newTraversal = new JsonTraversalExpression( traversal.Expression, traversal.Path, returnsText: false, lastPathComponent.Type, _sqlExpressionFactory.FindMapping(lastPathComponent.Type)); var jsonMapping = (NpgsqlJsonTypeMapping)traversal.Expression.TypeMapping; return(_sqlExpressionFactory.Function( jsonMapping.IsJsonb ? "jsonb_array_length" : "json_array_length", new[] { newTraversal }, typeof(int))); } return(null); }
public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments) { if (method.DeclaringType != typeof(JsonElement) || !(instance.TypeMapping is NpgsqlJsonTypeMapping mapping)) { return(null); } if (method == GetProperty || method == ArrayIndexer) { // The first time we see a JSON traversal it's on a column - create a JsonTraversalExpression. // Traversals on top of that get appended into the same expression. return(instance is ColumnExpression columnExpression ? _sqlExpressionFactory.JsonTraversal(columnExpression, arguments, false, typeof(string), mapping) : instance is JsonTraversalExpression prevPathTraversal ? prevPathTraversal.Append(_sqlExpressionFactory.ApplyDefaultTypeMapping(arguments[0])) : null); } if (GetMethods.Contains(method.Name) && arguments.Count == 0 && instance is JsonTraversalExpression traversal) { var traversalToText = new JsonTraversalExpression( traversal.Expression, traversal.Path, returnsText: true, typeof(string), _stringTypeMapping); return(method.Name == nameof(JsonElement.GetString) ? traversalToText : ConvertFromText(traversalToText, method.ReturnType)); } if (method == GetArrayLength) { return(_sqlExpressionFactory.Function( mapping.IsJsonb ? "jsonb_array_length" : "json_array_length", new[] { instance }, typeof(int))); } if (method.Name.StartsWith("TryGet") && arguments.Count == 0) { throw new InvalidOperationException($"The TryGet* methods on {nameof(JsonElement)} aren't translated yet, use Get* instead.'"); } return(null); }