public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, BinaryExpression expression) { var isValueExpressionOnRight = expression.Right.IsValueExpression(); var jsonLocatorExpression = isValueExpressionOnRight ? expression.Left : expression.Right; var valueExpression = isValueExpressionOnRight ? expression.Right : expression.Left; var members = FindMembers.Determine(jsonLocatorExpression); var field = mapping.FieldFor(members); var value = field.GetValue(valueExpression); var jsonLocator = field.SqlLocator; var useContainment = mapping.PropertySearching == PropertySearching.ContainmentOperator || field.ShouldUseContainmentOperator(); var isDuplicated = (mapping.FieldFor(members) is DuplicatedField); if (useContainment && expression.NodeType == ExpressionType.Equal && value != null && !isDuplicated) { return(new ContainmentWhereFragment(serializer, expression, _wherePrefix)); } if (value == null) { var sql = expression.NodeType == ExpressionType.NotEqual ? $"({jsonLocator}) is not null" : $"({jsonLocator}) {_isOperator} null"; return(new WhereFragment(sql)); } var op = _operators[expression.NodeType]; if (jsonLocatorExpression.NodeType == ExpressionType.Modulo) { var byValue = moduloByValue((isValueExpressionOnRight ? expression.Left : expression.Right) as BinaryExpression); var moduloFormat = isValueExpressionOnRight ? "{0} % {1} {2} ?" : "? {2} {0} % {1}"; return(new WhereFragment(moduloFormat.ToFormat(jsonLocator, byValue, op), value)); } // ! == -> <> if (expression.Left.NodeType == ExpressionType.Not && expression.NodeType == ExpressionType.Equal) { op = _operators[ExpressionType.NotEqual]; } var whereFormat = isValueExpressionOnRight ? "{0} {1} ?" : "? {1} {0}"; return(new WhereFragment($"{_wherePrefix}{whereFormat.ToFormat(jsonLocator, op)}", value)); return(value == null ? new WhereFragment($"({jsonLocator}) {_isOperator} null") : new WhereFragment($"{_wherePrefix}({jsonLocator}) {op} ?", value)); }
// TODO -- pull this out somewhere else private IWhereFragment buildSimpleWhereClause(IQueryableDocument mapping, BinaryExpression binary) { var isValueExpressionOnRight = binary.Right.IsValueExpression(); var jsonLocatorExpression = isValueExpressionOnRight ? binary.Left : binary.Right; var valueExpression = isValueExpressionOnRight ? binary.Right : binary.Left; var op = _operators[binary.NodeType]; var isSubQuery = isValueExpressionOnRight ? binary.Left is SubQueryExpression : binary.Right is SubQueryExpression; if (isSubQuery) { return(buildChildCollectionQuery(mapping, jsonLocatorExpression.As <SubQueryExpression>().QueryModel, valueExpression, op)); } var members = FindMembers.Determine(jsonLocatorExpression); var field = mapping.FieldFor(members); var value = field.GetValue(valueExpression); var jsonLocator = field.SqlLocator; var useContainment = mapping.PropertySearching == PropertySearching.ContainmentOperator || field.ShouldUseContainmentOperator(); var isDuplicated = (mapping.FieldFor(members) is DuplicatedField); if (useContainment && binary.NodeType == ExpressionType.Equal && value != null && !isDuplicated) { return(new ContainmentWhereFragment(_serializer, binary)); } if (value == null) { var sql = binary.NodeType == ExpressionType.NotEqual ? $"({jsonLocator}) is not null" : $"({jsonLocator}) is null"; return(new WhereFragment(sql)); } if (jsonLocatorExpression.NodeType == ExpressionType.Modulo) { var moduloByValue = MartenExpressionParser.moduloByValue(binary); return(new WhereFragment("{0} % {1} {2} ?".ToFormat(jsonLocator, moduloByValue, op), value)); } return(new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value)); }
protected override Expression VisitMember(MemberExpression node) { _lastMember = _mapping.FieldFor(new[] { node.Member }); if (node.NodeType != ExpressionType.MemberAccess || node.Member.DeclaringType != _queryType) { return(base.VisitMember(node)); } string methodName; switch (node.Member) { case PropertyInfo _: methodName = nameof(CreatePropertyParameterSetter); break; case FieldInfo _: methodName = nameof(CreateFieldParameterSetter); break; default: throw new NotSupportedException("Only Property or Field is supported for query parameter"); } var method = GetType() .GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) .MakeGenericMethod(_queryType); ParameterSetters.Add((IDbParameterSetter)method.Invoke(this, new[] { node.Member })); return(base.VisitMember(node)); }
private static IField GetField(IQueryableDocument mapping, MethodCallExpression expression) { IField GetField(Expression e) { var visitor = new FindMembers(); visitor.Visit(e); var field = mapping.FieldFor(visitor.Members); return(field); } if (!expression.Method.IsStatic && expression.Object != null && expression.Object.NodeType != ExpressionType.Constant) { // x.member.Equals(...) return(GetField(expression.Object)); } if (expression.Arguments[0].NodeType == ExpressionType.Constant) { // type.Equals("value", x.member) [decimal] return(GetField(expression.Arguments[1])); } // type.Equals(x.member, "value") [decimal] return(GetField(expression.Arguments[0])); }
public SelectManyQuery(IDocumentSchema schema, IQueryableDocument mapping, QueryModel query, int index) { Index = index; _schema = schema; _query = query; _from = query.BodyClauses[index - 1].As <AdditionalFromClause>(); var members = FindMembers.Determine(_from.FromExpression); _field = mapping.FieldFor(members); IsDistinct = query.HasOperator <DistinctResultOperator>(); var next = query.BodyClauses.Skip(index + 1).FirstOrDefault(x => x is AdditionalFromClause); if (next != null) { throw new NotSupportedException("Not yet supporting SelectMany().SelectMany()"); } else { _take = _query.BodyClauses.Count - index; } _tableAlias = "sub" + Index; _documentType = _field.MemberType.GetElementType(); _document = _schema.StoreOptions.GetChildDocument(_tableAlias + ".x", _documentType); }
public string ToJsonBuildObjectPair(IQueryableDocument mapping) { var field = mapping.FieldFor(Field.ToArray()); var locator = field.SelectionLocator ?? field.SqlLocator; return($"'{Name}', {locator}"); }
public void AppendJoin(CommandBuilder sql, string rootTableAlias, IQueryableDocument document) { var locator = document == null ? _field.LocatorFor(rootTableAlias) : document.FieldFor(_field.Members).LocatorFor(rootTableAlias); var joinOperator = JoinType == JoinType.Inner ? InnerJoin : OuterJoin; sql.Append(joinOperator); sql.Append(" "); if (IsSoftDeleted) { sql.Append("(select * from "); sql.Append(_mapping.Table.QualifiedName); sql.Append(" where "); sql.Append(DocumentMapping.DeletedColumn); sql.Append(" = False)"); } else { sql.Append(_mapping.Table.QualifiedName); } sql.Append(" as "); sql.Append(TableAlias); sql.Append(" ON "); sql.Append(locator); sql.Append(" = "); sql.Append(TableAlias); sql.Append(".id"); }
public string ToJsonBuildObjectPair(IQueryableDocument mapping) { var locator = mapping.FieldFor(Field.Members).SelectionLocator; return($"'{Setter.Name}', {locator}"); }
public SelectManyQuery(DocumentStore store, IQueryableDocument mapping, QueryModel query, int index) { Index = index; _store = store; _query = query; _from = query.BodyClauses[index - 1].As <AdditionalFromClause>(); _field = mapping.FieldFor(_from.FromExpression); IsDistinct = query.HasOperator <DistinctResultOperator>(); var next = query.BodyClauses.Skip(index + 1).FirstOrDefault(x => x is AdditionalFromClause); if (next != null) { throw new NotSupportedException("Not yet supporting SelectMany().SelectMany()"); } _take = _query.BodyClauses.Count - index; _tableAlias = "sub" + Index; _documentType = _field.FieldType.DeriveElementType(); _document = _store.Options.GetChildDocument(_tableAlias + ".x", _documentType); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var members = FindMembers.Determine(expression); var field = mapping.FieldFor(members); return new WhereFragment($"({field.SelectionLocator} is null or jsonb_array_length({field.SelectionLocator}) = 0)"); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var members = FindMembers.Determine(expression); var field = mapping.FieldFor(members); return(new WhereFragment($"({field.SelectionLocator} is null or jsonb_array_length({field.SelectionLocator}) = 0)")); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var members = FindMembers.Determine(expression); var locator = mapping.FieldFor(members).SqlLocator; var value = expression.Arguments.Last().Value(); return(new WhereFragment($"{locator} ~~* ?", value.As <string>())); }
public static string JsonLocator(this IQueryableDocument mapping, Expression expression) { var visitor = new FindMembers(); visitor.Visit(expression); var field = mapping.FieldFor(visitor.Members); return(field.SqlLocator); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { MemberInfo[] members = FindMembers.Determine(expression); string locator = mapping.FieldFor(members).SqlLocator; object values = expression.Arguments.Last().Value(); string json = serializer.ToJson(values); return(new CustomizableWhereFragment($"{locator} @> ?", "?", Tuple.Create <object, NpgsqlDbType?>(json, NpgsqlDbType.Jsonb))); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var finder = new FindMembers(); finder.Visit(expression); var members = finder.Members; var locator = mapping.FieldFor(members).SqlLocator; var values = expression.Object.Value(); return new WhereFragment($"{locator} = ANY(?)", values); }
public string JoinTextFor(string rootTableAlias, IQueryableDocument document = null) { var locator = document == null ? _field.LocatorFor(rootTableAlias) : document.FieldFor(_field.Members).LocatorFor(rootTableAlias); var joinOperator = JoinType == JoinType.Inner ? "INNER JOIN" : "LEFT OUTER JOIN"; return($"{joinOperator} {_mapping.Table.QualifiedName} as {TableAlias} ON {locator} = {TableAlias}.id"); }
protected override Expression VisitMember(MemberExpression node) { _lastMember = _mapping.FieldFor(new MemberInfo[] { node.Member }); if (node.NodeType == ExpressionType.MemberAccess && node.Member.ReflectedType == _queryType) { var property = (PropertyInfo)node.Member; var method = GetType().GetMethod(nameof(CreateParameterSetter), BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(_queryType, property.PropertyType); var result = (IDbParameterSetter)method.Invoke(this, new [] { property }); _parameterSetters.Add(result); } return(base.VisitMember(node)); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var finder = new FindMembers(); finder.Visit(expression); var members = finder.Members; var locator = mapping.FieldFor(members).SqlLocator; var values = expression.Object.Value(); return(new WhereFragment($"{locator} = ANY(?)", values)); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var members = FindMembers.Determine(expression); var locator = mapping.FieldFor(members).SqlLocator; var values = expression.Arguments.Last().Value(); if (members.Last().GetMemberType().GetTypeInfo().IsEnum) { return new EnumIsOneOfWhereFragment(values, serializer.EnumStorage, locator); } return new WhereFragment($"{locator} = ANY(?)", values); }
private IWhereFragment buildChildCollectionQuery(IQueryableDocument mapping, QueryModel query, Expression valueExpression, string op) { var members = FindMembers.Determine(query.MainFromClause.FromExpression); var field = mapping.FieldFor(members); if (query.HasOperator <CountResultOperator>()) { var value = field.GetValue(valueExpression); return(new WhereFragment($"jsonb_array_length({field.SqlLocator}) {op} ?", value)); } throw new NotSupportedException("Marten does not yet support this type of Linq query against child collections"); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var members = FindMembers.Determine(expression); var locator = mapping.FieldFor(members).SqlLocator; var values = expression.Arguments.Last().Value(); if (members.Last().GetMemberType().IsEnum) { return(new EnumIsNotOneOfWhereFragment(values, serializer.EnumStorage, locator)); } return(new WhereFragment($"NOT({locator} = ANY(?))", values)); }
public string JoinTextFor(string rootTableAlias, IQueryableDocument document = null) { var locator = document == null ? _field.LocatorFor(rootTableAlias) : document.FieldFor(_field.Members).LocatorFor(rootTableAlias); var joinOperator = JoinType == JoinType.Inner ? "INNER JOIN" : "LEFT OUTER JOIN"; // Right here, if this doc type is soft deleted, use a subquery in place of the table name var subquery = IsSoftDeleted ? $"(select * from {_mapping.Table.QualifiedName} where {DocumentMapping.DeletedColumn} = False)" : _mapping.Table.QualifiedName; return($"{joinOperator} {subquery} as {TableAlias} ON {locator} = {TableAlias}.id"); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var finder = new FindMembers(); finder.Visit(expression); var members = finder.Members; var fieldlocator = mapping.FieldFor(members).SqlLocator; if (IsCollectionContainsWithStringKey(expression.Method)) { return QueryFromICollectionContains(expression, fieldlocator, serializer); } else if (IsDictionaryContainsKey(expression.Method)) { return QueryFromDictionaryContainsKey(expression, fieldlocator); } else throw new NotImplementedException("Could not understand the format of the dictionary access"); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var finder = new FindMembers(); finder.Visit(expression); var members = finder.Members; var locator = mapping.FieldFor(members).SqlLocator; var values = expression.Arguments.Last().Value(); if (members.Last().GetMemberType().GetTypeInfo().IsEnum) { return(new EnumIsOneOfWhereFragment(values, serializer.EnumStorage, locator)); } return(new WhereFragment($"{locator} = ANY(?)", values)); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var finder = new FindMembers(); finder.Visit(expression); var members = finder.Members; var fieldlocator = mapping.FieldFor(members).SqlLocator; if (IsCollectionContainsWithStringKey(expression.Method)) { return(QueryFromICollectionContains(expression, fieldlocator, serializer)); } else if (IsDictionaryContainsKey(expression.Method)) { return(QueryFromDictionaryContainsKey(expression, fieldlocator)); } else { throw new NotImplementedException("Could not understand the format of the dictionary access"); } }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var locator = mapping.FieldFor(new MemberInfo[] {_property}).SqlLocator; return new WhereFragment($"{locator} = 'Blue'"); }
public SingleFieldSelector(IQueryableDocument mapping, MemberInfo[] members) : base(mapping.FieldFor(members).TypedLocator) { }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression) { var locator = mapping.FieldFor(new MemberInfo[] { _property }).SqlLocator; return(new WhereFragment($"{locator} = 'Blue'")); }
private string buildSubQuery(SubQueryExpression subQuery, CommandBuilder command) { var contains = subQuery.QueryModel.ResultOperators.OfType <ContainsResultOperator>().FirstOrDefault(); if (contains == null) { throw new NotSupportedException("Only the Contains() operator is supported on subqueries within Collection.Any() searches"); } // build rhs of ?| var from = subQuery.QueryModel.MainFromClause.FromExpression as ConstantExpression; if (from == null || !supportedTypes.Any(supp => isListOrArrayOf(from.Type, supp))) { throwNotSupportedContains(); } //TODO: this won't work for enumeration types. Only works with strings, so we have // to exactly map the ToString() like the underlying serializer would. Blech. var values = new List <string>(); var enumerable = ((System.Collections.IEnumerable)from.Value); foreach (var obj in enumerable) { values.Add(obj.ToString()); } var fromParam = command.AddParameter(values.ToArray()); fromParam.NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Text; // check/build lhs of ?| var item = contains.Item as QuerySourceReferenceExpression; if (item == null) { throwNotSupportedContains(); } if (!supportedTypes.Any(supp => supp == item.ReferencedQuerySource.ItemType)) { throwNotSupportedContains(); } var itemSource = item.ReferencedQuerySource as MainFromClause; if (itemSource == null) { throwNotSupportedContains(); } var member = itemSource.FromExpression as MemberExpression; if (member == null) { throwNotSupportedContains(); } var visitor = new FindMembers(); visitor.Visit(member); var members = visitor.Members; if (!members.Any()) { throwNotSupportedContains(); } var path = _mapping?.FieldFor(members).SqlLocator ?? $"CAST ({CommandBuilder.BuildJsonStringLocator("d.data", members.ToArray(), _serializer.Casing)} as jsonb)"; return($"{path} ?| :{fromParam.ParameterName}"); }
public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, BinaryExpression expression) { var areBothMemberExpressions = !expression.Left.IsValueExpression() && !expression.Right.IsValueExpression(); var isValueExpressionOnRight = areBothMemberExpressions || expression.Right.IsValueExpression(); var jsonLocatorExpression = isValueExpressionOnRight ? expression.Left : expression.Right; var valueExpression = isValueExpressionOnRight ? expression.Right : expression.Left; var members = FindMembers.Determine(jsonLocatorExpression); var field = mapping.FieldFor(members); object value; if (valueExpression is MemberExpression memberAccess) { var membersOther = FindMembers.Determine(memberAccess); var fieldOther = mapping.FieldFor(membersOther); value = fieldOther.SqlLocator; } else { memberAccess = null; value = field.GetValue(valueExpression); } var jsonLocator = field.SqlLocator; var useContainment = mapping.PropertySearching == PropertySearching.ContainmentOperator || field.ShouldUseContainmentOperator(); var isDuplicated = (mapping.FieldFor(members) is DuplicatedField); var isEnumString = field.MemberType.GetTypeInfo().IsEnum&& serializer.EnumStorage == EnumStorage.AsString; if (useContainment && expression.NodeType == ExpressionType.Equal && value != null && !isDuplicated && !isEnumString) { return(new ContainmentWhereFragment(serializer, expression, _wherePrefix)); } if (value == null) { var sql = expression.NodeType == ExpressionType.NotEqual ? $"({jsonLocator}) is not null" : $"({jsonLocator}) {_isOperator} null"; return(new WhereFragment(sql)); } var op = _operators[expression.NodeType]; if (jsonLocatorExpression.NodeType == ExpressionType.Modulo) { var byValue = moduloByValue((isValueExpressionOnRight ? expression.Left : expression.Right) as BinaryExpression); var moduloFormat = isValueExpressionOnRight ? "{0} % {1} {2} ?" : "? {2} {0} % {1}"; return(new WhereFragment(moduloFormat.ToFormat(jsonLocator, byValue, op), value)); } // ! == -> <> if (expression.Left.NodeType == ExpressionType.Not && expression.NodeType == ExpressionType.Equal) { op = _operators[ExpressionType.NotEqual]; } if (memberAccess != null) { return(new WhereFragment($"{_wherePrefix}{jsonLocator} {op} {value}")); } var whereFormat = isValueExpressionOnRight ? "{0} {1} ?" : "? {1} {0}"; return(new WhereFragment($"{_wherePrefix}{whereFormat.ToFormat(jsonLocator, op)}", value)); //return value == null ? new WhereFragment($"({jsonLocator}) {_isOperator} null") : new WhereFragment($"{_wherePrefix}({jsonLocator}) {op} ?", value); }
// TODO -- pull this out somewhere else private IWhereFragment buildSimpleWhereClause(IQueryableDocument mapping, BinaryExpression binary) { var isValueExpressionOnRight = binary.Right.IsValueExpression(); var jsonLocatorExpression = isValueExpressionOnRight ? binary.Left : binary.Right; var valueExpression = isValueExpressionOnRight ? binary.Right : binary.Left; var op = _operators[binary.NodeType]; var isSubQuery = isValueExpressionOnRight ? binary.Left is SubQueryExpression : binary.Right is SubQueryExpression; if (isSubQuery) { return buildChildCollectionQuery(mapping, jsonLocatorExpression.As<SubQueryExpression>().QueryModel, valueExpression, op); } var members = FindMembers.Determine(jsonLocatorExpression); var field = mapping.FieldFor(members); var value = field.GetValue(valueExpression); var jsonLocator = field.SqlLocator; var useContainment = mapping.PropertySearching == PropertySearching.ContainmentOperator || field.ShouldUseContainmentOperator(); var isDuplicated = (mapping.FieldFor(members) is DuplicatedField); if (useContainment && binary.NodeType == ExpressionType.Equal && value != null && !isDuplicated) { return new ContainmentWhereFragment(_serializer, binary); } if (value == null) { var sql = binary.NodeType == ExpressionType.NotEqual ? $"({jsonLocator}) is not null" : $"({jsonLocator}) is null"; return new WhereFragment(sql); } if (jsonLocatorExpression.NodeType == ExpressionType.Modulo) { var moduloByValue = MartenExpressionParser.moduloByValue(binary); return new WhereFragment("{0} % {1} {2} ?".ToFormat(jsonLocator, moduloByValue, op), value); } return new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value); }
private IWhereFragment buildChildCollectionQuery(IQueryableDocument mapping, QueryModel query, Expression valueExpression, string op) { var members = FindMembers.Determine(query.MainFromClause.FromExpression); var field = mapping.FieldFor(members); if (query.HasOperator<CountResultOperator>()) { var value = field.GetValue(valueExpression); return new WhereFragment($"jsonb_array_length({field.SqlLocator}) {op} ?", value); } throw new NotSupportedException("Marten does not yet support this type of Linq query against child collections"); }
public SingleFieldSelector(IQueryableDocument mapping, MemberInfo[] members, bool distinct) : base(distinct, mapping.FieldFor(members).SqlLocator) { }