internal T this[int index]
 {
     get
     {
         var row       = NativeResults.get_row(ResultsHandle, (IntPtr)index);
         var rowHandle = Realm.CreateRowHandle(row, _realm.SharedRealmHandle);
         return((T)(object)_realm.MakeObjectForRow(typeof(T), rowHandle));
     }
 }
Example #2
0
        public static T GetObject <T>(Realm realm, TableHandle table, IntPtr columnIndex, IntPtr rowIndex, string objectType) where T : RealmObject
        {
            var linkedRowPtr = NativeTable.GetLink(table, columnIndex, rowIndex);

            if (linkedRowPtr == IntPtr.Zero)
            {
                return(null);
            }

            return((T)realm.MakeObjectForRow(objectType, linkedRowPtr));
        }
Example #3
0
 internal T this[int index]
 {
     get
     {
         if (index < 0)
         {
             throw new ArgumentOutOfRangeException();
         }
         var rowPtr = ResultsHandle.GetRow(index);
         return((T)(object)_realm.MakeObjectForRow(_targetMetadata, rowPtr));
     }
 }
Example #4
0
        public T this[int index]
        {
            get
            {
                if (index < 0)
                {
                    throw new ArgumentOutOfRangeException();
                }
                var linkedRowPtr = _listHandle.Get((IntPtr)index);
                return((T)_realm.MakeObjectForRow(_targetMetadata, linkedRowPtr));
            }

            set
            {
                throw new NotImplementedException();
            }
        }
Example #5
0
        protected T GetObjectValue <T>(string propertyName) where T : RealmObject
        {
            Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted");

            var rowIndex     = _rowHandle.RowIndex;
            var linkedRowPtr = NativeTable.GetLink(_metadata.Table, _metadata.ColumnIndices[propertyName], rowIndex);

            if (linkedRowPtr == IntPtr.Zero)
            {
                return(null);
            }

            Schema.Property property;
            _metadata.Schema.TryFindProperty(propertyName, out property);
            var objectType = property.ObjectType;

            return((T)_realm.MakeObjectForRow(objectType, linkedRowPtr));
        }
        /// <summary>
        ///  Move the iterator to the next related object, starting "before" the first object.
        /// </summary>
        /// <remarks>
        /// Is a factory for RealmObjects, loading a new one and updating <c>Current</c>.
        /// </remarks>
        /// <returns>True only if can advance.</returns>
        public bool MoveNext()
        {
            if (_enumeratingResults == null)
            {
                return(false);
            }

            ++_index;
            var rowPtr = _enumeratingResults.GetRow(_index);

            if (rowPtr == IntPtr.Zero)
            {
                Current = (T)(object)null;
                return(false);
            }
            Current = (T)(object)_realm.MakeObjectForRow(_schema.Name, rowPtr);
            return(true);
        }
        /// <summary>
        ///  Move the iterator to the next related object, starting "before" the first object.
        /// </summary>
        /// <returns>True only if can advance.</returns>
        public bool MoveNext()
        {
            if (_enumeratingResults == null)
            {
                return(false);
            }

            ++_index;
            var    rowPtr    = NativeResults.get_row(_enumeratingResults, (IntPtr)_index);
            var    rowHandle = Realm.CreateRowHandle(rowPtr, _realm.SharedRealmHandle);
            object nextObj   = null;

            if (!rowHandle.IsInvalid)
            {
                nextObj = _realm.MakeObjectForRow(_retType, rowHandle);
            }
            Current = (T)nextObj;
            return(nextObj != null);
        }
        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(Queryable))
            {
                if (m.Method.Name == nameof(Queryable.Where))
                {
                    this.Visit(m.Arguments[0]);
                    LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
                    this.Visit(lambda.Body);
                    return(m);
                }
                if (m.Method.Name == nameof(Queryable.OrderBy))
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), true, true);
                    return(m);
                }
                if (m.Method.Name == nameof(Queryable.OrderByDescending))
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), true, false);
                    return(m);
                }
                if (m.Method.Name == nameof(Queryable.ThenBy))
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), false, true);
                    return(m);
                }
                if (m.Method.Name == nameof(Queryable.ThenByDescending))
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), false, false);
                    return(m);
                }
                if (m.Method.Name == nameof(Queryable.Count))
                {
                    RecurseToWhereOrRunLambda(m);
                    var foundCount = _coreQueryHandle.Count();
                    return(Expression.Constant(foundCount));
                }
                if (m.Method.Name == nameof(Queryable.Any))
                {
                    RecurseToWhereOrRunLambda(m);
                    bool foundAny = _coreQueryHandle.FindDirect(IntPtr.Zero) != IntPtr.Zero;
                    return(Expression.Constant(foundAny));
                }
                if (m.Method.Name.StartsWith(nameof(Queryable.First)))
                {
                    RecurseToWhereOrRunLambda(m);
                    IntPtr firstRowPtr = IntPtr.Zero;
                    if (OptionalSortDescriptorBuilder == null)
                    {
                        firstRowPtr = _coreQueryHandle.FindDirect(IntPtr.Zero);
                    }
                    else
                    {
                        using (ResultsHandle rh = _realm.MakeResultsForQuery(_coreQueryHandle, OptionalSortDescriptorBuilder))
                        {
                            firstRowPtr = rh.GetRow(0);
                        }
                    }
                    if (firstRowPtr != IntPtr.Zero)
                    {
                        return(Expression.Constant(_realm.MakeObjectForRow(_metadata, firstRowPtr)));
                    }
                    if (m.Method.Name == nameof(Queryable.First))
                    {
                        throw new InvalidOperationException("Sequence contains no matching element");
                    }
                    Debug.Assert(m.Method.Name == nameof(Queryable.FirstOrDefault));
                    return(Expression.Constant(null));
                }

/*
 * // FIXME: See discussion in the test DefaultIfEmptyReturnsDefault
 * // kept because it shows part of what might be a viable implementation if can work out architectural issues
 *
 *              if (m.Method.Name == nameof(Queryable.DefaultIfEmpty))
 *              {
 *                  RecurseToWhereOrRunLambda(m);
 *                  IntPtr firstRowPtr = _coreQueryHandle.FindDirect(IntPtr.Zero);
 *                  if (firstRowPtr != IntPtr.Zero)
 *                      return m;  // as if just a "Where"
 *                  var innerType = m.Type.GetGenericArguments()[0];
 *                  var listType = typeof(List<>).MakeGenericType(innerType);
 *                  var singleNullItemList = Activator.CreateInstance(listType);
 *                  ((IList)singleNullItemList).Add(null);
 *                  return Expression.Constant(singleNullItemList);
 *              }
 */
                if (m.Method.Name.StartsWith(nameof(Queryable.Single)))  // same as unsorted First with extra checks
                {
                    RecurseToWhereOrRunLambda(m);
                    var firstRowPtr = _coreQueryHandle.FindDirect(IntPtr.Zero);
                    if (firstRowPtr == IntPtr.Zero)
                    {
                        if (m.Method.Name == nameof(Queryable.Single))
                        {
                            throw new InvalidOperationException("Sequence contains no matching element");
                        }
                        Debug.Assert(m.Method.Name == nameof(Queryable.SingleOrDefault));
                        return(Expression.Constant(null));
                    }
                    var    firstRow   = Realm.CreateRowHandle(firstRowPtr, _realm.SharedRealmHandle);
                    IntPtr nextIndex  = (IntPtr)(firstRow.RowIndex + 1);
                    var    nextRowPtr = _coreQueryHandle.FindDirect(nextIndex);
                    if (nextRowPtr != IntPtr.Zero)
                    {
                        throw new InvalidOperationException("Sequence contains more than one matching element");
                    }
                    return(Expression.Constant(_realm.MakeObjectForRow(_metadata, firstRow)));
                }
                if (m.Method.Name.StartsWith(nameof(Queryable.Last)))
                {
                    RecurseToWhereOrRunLambda(m);

                    var lastRowPtr = IntPtr.Zero;
                    using (ResultsHandle rh = _realm.MakeResultsForQuery(_coreQueryHandle, OptionalSortDescriptorBuilder))
                    {
                        var lastIndex = rh.Count() - 1;
                        if (lastIndex >= 0)
                        {
                            lastRowPtr = rh.GetRow(lastIndex);
                        }
                    }
                    if (lastRowPtr != IntPtr.Zero)
                    {
                        return(Expression.Constant(_realm.MakeObjectForRow(_metadata, lastRowPtr)));
                    }
                    if (m.Method.Name == nameof(Queryable.Last))
                    {
                        throw new InvalidOperationException("Sequence contains no matching element");
                    }
                    Debug.Assert(m.Method.Name == nameof(Queryable.LastOrDefault));
                    return(Expression.Constant(null));
                }
                if (m.Method.Name.StartsWith(nameof(Queryable.ElementAt)))
                {
                    var row = VisitElementAt(m);
                    if (row == null || row.IsInvalid)
                    {
                        if (m.Method.Name == nameof(Queryable.ElementAt))
                        {
                            throw new ArgumentOutOfRangeException();
                        }
                        Debug.Assert(m.Method.Name == nameof(Queryable.ElementAtOrDefault));
                        return(Expression.Constant(null));
                    }
                    return(Expression.Constant(_realm.MakeObjectForRow(_metadata, row)));
                }
            }

            if (m.Method.DeclaringType == typeof(string))
            {
                QueryHandle.Operation <string> queryMethod = null;

                if (m.Method == Methods.String.Contains.Value)
                {
                    queryMethod = (q, c, v) => q.StringContains(c, v);
                }
                else if (m.Method == Methods.String.StartsWith.Value)
                {
                    queryMethod = (q, c, v) => q.StringStartsWith(c, v);
                }
                else if (m.Method == Methods.String.EndsWith.Value)
                {
                    queryMethod = (q, c, v) => q.StringEndsWith(c, v);
                }
                else if (m.Method == Methods.String.IsNullOrEmpty.Value)
                {
                    var member = m.Arguments.SingleOrDefault() as MemberExpression;
                    if (member == null)
                    {
                        throw new NotSupportedException($"The method '{m.Method}' has to be invoked with a RealmObject member");
                    }
                    var columnIndex = _coreQueryHandle.GetColumnIndex(member.Member.Name);

                    _coreQueryHandle.GroupBegin();
                    _coreQueryHandle.NullEqual(columnIndex);
                    _coreQueryHandle.Or();
                    _coreQueryHandle.StringEqual(columnIndex, string.Empty);
                    _coreQueryHandle.GroupEnd();
                    return(m);
                }

                if (queryMethod != null)
                {
                    var member = m.Object as MemberExpression;
                    if (member == null)
                    {
                        throw new NotSupportedException($"The method '{m.Method}' has to be invoked on a RealmObject member");
                    }
                    var columnIndex = _coreQueryHandle.GetColumnIndex(member.Member.Name);

                    object argument;
                    if (!TryExtractConstantValue(m.Arguments.SingleOrDefault(), out argument) || argument.GetType() != typeof(string))
                    {
                        throw new NotSupportedException($"The method '{m.Method}' has to be invoked with a single string constant argument or closure variable");
                    }
                    queryMethod(_coreQueryHandle, columnIndex, (string)argument);
                    return(m);
                }
            }

            throw new NotSupportedException($"The method '{m.Method.Name}' is not supported");
        }
        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(Queryable))
            {
                if (m.Method.Name == "Where")
                {
                    this.Visit(m.Arguments[0]);
                    LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
                    this.Visit(lambda.Body);
                    return(m);
                }
                if (m.Method.Name == "OrderBy")
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), true, true);
                    return(m);
                }
                if (m.Method.Name == "OrderByDescending")
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), true, false);
                    return(m);
                }
                if (m.Method.Name == "ThenBy")
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), false, true);
                    return(m);
                }
                if (m.Method.Name == "ThenByDescending")
                {
                    this.Visit(m.Arguments[0]);
                    AddSort((LambdaExpression)StripQuotes(m.Arguments[1]), false, false);
                    return(m);
                }
                if (m.Method.Name == "Count")
                {
                    RecurseToWhereOrRunLambda(m);
                    int foundCount = (int)NativeQuery.count(_coreQueryHandle);
                    return(Expression.Constant(foundCount));
                }
                if (m.Method.Name == "Any")
                {
                    RecurseToWhereOrRunLambda(m);
                    var  rowPtr   = NativeQuery.findDirect(_coreQueryHandle, IntPtr.Zero);
                    var  firstRow = Realm.CreateRowHandle(rowPtr, _realm.SharedRealmHandle);
                    bool foundAny = !firstRow.IsInvalid;
                    return(Expression.Constant(foundAny));
                }
                if (m.Method.Name == "First")
                {
                    RecurseToWhereOrRunLambda(m);
                    RowHandle firstRow = null;
                    if (_optionalSortOrderHandle == null)
                    {
                        var rowPtr = NativeQuery.findDirect(_coreQueryHandle, IntPtr.Zero);
                        firstRow = Realm.CreateRowHandle(rowPtr, _realm.SharedRealmHandle);
                    }
                    else
                    {
                        using (ResultsHandle rh = _realm.MakeResultsForQuery(_retType, _coreQueryHandle, _optionalSortOrderHandle))
                        {
                            var rowPtr = NativeResults.get_row(rh, IntPtr.Zero);
                            firstRow = Realm.CreateRowHandle(rowPtr, _realm.SharedRealmHandle);
                        }
                    }
                    if (firstRow == null || firstRow.IsInvalid)
                    {
                        throw new InvalidOperationException("Sequence contains no matching element");
                    }
                    return(Expression.Constant(_realm.MakeObjectForRow(_retType, firstRow)));
                }
                if (m.Method.Name == "Single")  // same as unsorted First with extra checks
                {
                    RecurseToWhereOrRunLambda(m);
                    var rowPtr   = NativeQuery.findDirect(_coreQueryHandle, IntPtr.Zero);
                    var firstRow = Realm.CreateRowHandle(rowPtr, _realm.SharedRealmHandle);
                    if (firstRow.IsInvalid)
                    {
                        throw new InvalidOperationException("Sequence contains no matching element");
                    }
                    IntPtr nextIndex  = (IntPtr)(firstRow.RowIndex + 1);
                    var    nextRowPtr = NativeQuery.findDirect(_coreQueryHandle, nextIndex);
                    var    nextRow    = Realm.CreateRowHandle(nextRowPtr, _realm.SharedRealmHandle);
                    if (!nextRow.IsInvalid)
                    {
                        throw new InvalidOperationException("Sequence contains more than one matching element");
                    }
                    return(Expression.Constant(_realm.MakeObjectForRow(_retType, firstRow)));
                }
            }

            if (m.Method.DeclaringType == typeof(string))
            {
                NativeQuery.Operation <string> queryMethod = null;

                if (m.Method == Methods.String.Contains.Value)
                {
                    queryMethod = (q, c, v) => NativeQuery.string_contains(q, c, v, (IntPtr)v.Length);
                }
                else if (m.Method == Methods.String.StartsWith.Value)
                {
                    queryMethod = (q, c, v) => NativeQuery.string_starts_with(q, c, v, (IntPtr)v.Length);
                }
                else if (m.Method == Methods.String.EndsWith.Value)
                {
                    queryMethod = (q, c, v) => NativeQuery.string_ends_with(q, c, v, (IntPtr)v.Length);
                }

                if (queryMethod != null)
                {
                    var member = m.Object as MemberExpression;
                    if (member == null)
                    {
                        throw new NotSupportedException($"The method '{m.Method}' has to be invoked on a RealmObject member");
                    }
                    var columnIndex = NativeQuery.get_column_index(_coreQueryHandle, member.Member.Name, (IntPtr)member.Member.Name.Length);

                    var argument = ExtractConstantValue(m.Arguments.SingleOrDefault());
                    if (argument == null || argument.GetType() != typeof(string))
                    {
                        throw new NotSupportedException($"The method '{m.Method}' has to be invoked with a single string constant argument or closure variable");
                    }
                    queryMethod(_coreQueryHandle, columnIndex, (string)argument);
                    return(m);
                }
            }

            throw new NotSupportedException($"The method '{m.Method.Name}' is not supported");
        }