protected unsafe void SetByteArrayValue(string propertyName, byte[] value) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); if (!_realm.IsInTransaction) { throw new RealmOutsideTransactionException("Cannot set values outside transaction"); } if (value == null) { NativeTable.set_null(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)_rowHandle.RowIndex); } else if (value.Length == 0) { // empty byte arrays are expressed in terms of a BinaryData object with a dummy pointer and zero size // that's how core differentiates between empty and null buffers NativeTable.set_binary(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)_rowHandle.RowIndex, (IntPtr)0x1, IntPtr.Zero); } else { fixed(byte *buffer = value) { NativeTable.set_binary(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)_rowHandle.RowIndex, (IntPtr)buffer, (IntPtr)value.LongLength); } } }
/// <summary> /// This realm will start managing a RealmObject which has been created as a standalone object. /// </summary> /// <typeparam name="T">The Type T must not only be a RealmObject but also have been processd by the Fody weaver, so it has persistent properties.</typeparam> /// <param name="obj">Must be a standalone object, null not allowed.</param> /// <exception cref="RealmOutsideTransactionException">If you invoke this when there is no write Transaction active on the realm.</exception> /// <exception cref="RealmObjectAlreadyManagedByRealmException">You can't manage the same object twice. This exception is thrown, rather than silently detecting the mistake, to help you debug your code</exception> /// <exception cref="RealmObjectManagedByAnotherRealmException">You can't manage an object with more than one realm</exception> public void Manage <T>(T obj) where T : RealmObject { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (obj.IsManaged) { if (obj.Realm.SharedRealmHandle == this.SharedRealmHandle) { throw new RealmObjectAlreadyManagedByRealmException("The object is already managed by this realm"); } throw new RealmObjectManagedByAnotherRealmException("Cannot start to manage an object with a realm when it's already managed by another realm"); } if (!IsInTransaction) { throw new RealmOutsideTransactionException("Cannot start managing a Realm object outside write transactions"); } var tableHandle = Metadata[typeof(T)].Table; var rowPtr = NativeTable.add_empty_row(tableHandle); var rowHandle = CreateRowHandle(rowPtr, SharedRealmHandle); obj._Manage(this, rowHandle); obj._CopyDataFromBackingFieldsToRow(); }
private RealmObject.Metadata CreateRealmObjectMetadata(Type realmObjectType) { var table = this.GetTable(realmObjectType); var wovenAtt = realmObjectType.GetCustomAttribute <WovenAttribute>(); if (wovenAtt == null) { throw new RealmException($"Fody not properly installed. {realmObjectType.FullName} is a RealmObject but has not been woven."); } var helper = (Weaving.IRealmObjectHelper)Activator.CreateInstance(wovenAtt.HelperType); var properties = realmObjectType.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public) .Where(p => p.GetCustomAttributes(false).OfType <WovenPropertyAttribute>().Any()) .Select(p => { var mapTo = p.GetCustomAttributes(false).OfType <MapToAttribute>().SingleOrDefault(); if (mapTo != null) { return(mapTo.Mapping); } return(p.Name); }) .ToDictionary(name => name, name => NativeTable.get_column_index(table, name, (IntPtr)name.Length)); return(new RealmObject.Metadata { Table = table, Helper = helper, ColumnIndices = properties }); }
protected bool GetBooleanValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; return(MarshalHelpers.IntPtrToBool(NativeTable.get_bool(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex))); }
protected double GetDoubleValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; return(NativeTable.get_double(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex)); }
public static double?GetNullableDouble(TableHandle tableHandle, IntPtr columnIndex, IntPtr rowIndex) { NativeException nativeException; double value; var hasValue = MarshalHelpers.IntPtrToBool(NativeTable.get_nullable_double(tableHandle, columnIndex, rowIndex, out value, out nativeException)); nativeException.ThrowIfNecessary(); return(hasValue ? value : (double?)null); }
public static bool?GetNullableBoolean(TableHandle tableHandle, IntPtr columnIndex, IntPtr rowIndex) { NativeException nativeException; IntPtr value; var hasValue = MarshalHelpers.IntPtrToBool(NativeTable.get_nullable_bool(tableHandle, columnIndex, rowIndex, out value, out nativeException)); nativeException.ThrowIfNecessary(); return(hasValue ? MarshalHelpers.IntPtrToBool(value) : (bool?)null); }
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.get_link(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex); return((T)MakeRealmObject(typeof(T), linkedRowPtr)); }
protected DateTimeOffset GetDateTimeOffsetValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; var unixTimeSeconds = NativeTable.get_datetime_seconds(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex); return(DateTimeOffsetExtensions.FromUnixTimeSeconds(unixTimeSeconds)); }
protected int GetInt32Value(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; var value = NativeTable.get_int64(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex); return((int)value); }
public static DateTimeOffset?GetNullableDateTimeOffset(TableHandle tableHandle, IntPtr columnIndex, IntPtr rowIndex) { NativeException nativeException; long ticks; var hasValue = MarshalHelpers.IntPtrToBool(NativeTable.get_nullable_timestamp_ticks(tableHandle, columnIndex, rowIndex, out ticks, out nativeException)); nativeException.ThrowIfNecessary(); return(hasValue ? new DateTimeOffset(ticks, TimeSpan.Zero) : (DateTimeOffset?)null); }
protected string GetStringValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; var badUTF8msg = $"Corrupted string UTF8 in {propertyName}"; int bufferSizeNeededChars = 128; // First alloc this thread if (_realm.stringGetBuffer == IntPtr.Zero) // first get of a string in this Realm { _realm.stringGetBuffer = Marshal.AllocHGlobal((IntPtr)(bufferSizeNeededChars * sizeof(char))); _realm.stringGetBufferLen = bufferSizeNeededChars; } bool isNull = false; // try to read int bytesRead = (int)NativeTable.get_string(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, _realm.stringGetBuffer, (IntPtr)_realm.stringGetBufferLen, out isNull); if (bytesRead == -1) { // bad UTF-8 data unable to transcode, vastly unlikely error but could be corrupt file throw new RealmInvalidDatabaseException(badUTF8msg); } if (bytesRead > _realm.stringGetBufferLen) // need a bigger buffer { Marshal.FreeHGlobal(_realm.stringGetBuffer); _realm.stringGetBuffer = Marshal.AllocHGlobal((IntPtr)(bytesRead * sizeof(char))); _realm.stringGetBufferLen = bytesRead; // try to read with big buffer bytesRead = (int)NativeTable.get_string(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, _realm.stringGetBuffer, (IntPtr)_realm.stringGetBufferLen, out isNull); if (bytesRead == -1) // bad UTF-8 in full string { throw new RealmInvalidDatabaseException(badUTF8msg); } Debug.Assert(bytesRead <= _realm.stringGetBufferLen); } // needed re-read with expanded buffer if (bytesRead == 0) { if (isNull) { return(null); } return(""); } return(Marshal.PtrToStringUni(_realm.stringGetBuffer, bytesRead)); // leaving buffer sitting allocated for quick reuse next time we read a string } // GetStringValue
protected DateTimeOffset?GetNullableDateTimeOffsetValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; long unixTimeSeconds = 0; var hasValue = MarshalHelpers.IntPtrToBool(NativeTable.get_nullable_datetime_seconds(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, ref unixTimeSeconds)); return(hasValue ? DateTimeOffsetExtensions.FromUnixTimeSeconds(unixTimeSeconds) : (DateTimeOffset?)null); }
protected bool?GetNullableBooleanValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; var retVal = IntPtr.Zero; var hasValue = MarshalHelpers.IntPtrToBool(NativeTable.get_nullable_bool(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, ref retVal)); return(hasValue ? MarshalHelpers.IntPtrToBool(retVal) : (bool?)null); }
protected double?GetNullableDoubleValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); var rowIndex = _rowHandle.RowIndex; var retVal = 0.0d; var hasValue = MarshalHelpers.IntPtrToBool(NativeTable.get_nullable_double(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, ref retVal)); return(hasValue ? retVal : (double?)null); }
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)); }
/// <summary> /// Fast lookup of an object for dynamic use, from a class which has a PrimaryKey property. /// </summary> /// <param name="className">Name of class in dynamic situation.</param> /// <param name="id">Id to be matched exactly, same as an == search.</param> /// <returns>Null or an object matdhing the id.</returns> /// <exception cref="RealmClassLacksPrimaryKeyException">If the RealmObject class lacks an [PrimaryKey].</exception> public RealmObject ObjectForPrimaryKey(string className, string id) { var metadata = Metadata[className]; var rowPtr = NativeTable.RowForPrimaryKey(metadata.Table, metadata.PrimaryKeyColumnIndex, id); if (rowPtr == IntPtr.Zero) { return(null); } return(MakeObjectForRow(metadata, rowPtr)); }
/// <summary> /// Removes a persistent object from this realm, effectively deleting it. /// </summary> /// <param name="obj">Must be an object persisted in this realm.</param> /// <exception cref="RealmOutsideTransactionException">If you invoke this when there is no write Transaction active on the realm.</exception> /// <exception cref="System.ArgumentNullException">If you invoke this with a standalone object.</exception> public void Remove(RealmObject obj) { if (!IsInTransaction) { throw new RealmOutsideTransactionException("Cannot remove Realm object outside write transactions"); } var tableHandle = Metadata[obj.GetType()].Table; NativeTable.remove_row(tableHandle, (RowHandle)obj.RowHandle); }
protected void SetByteArrayValue(string propertyName, byte[] value) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); if (!_realm.IsInTransaction) { throw new RealmOutsideTransactionException("Cannot set values outside transaction"); } NativeTable.SetByteArray(_metadata.Table, _metadata.ColumnIndices[propertyName], _rowHandle.RowIndex, value); }
/// <summary> /// Fast lookup of an object from a class which has a PrimaryKey property. /// </summary> /// <typeparam name="T">The Type T must be a RealmObject.</typeparam> /// <param name="id">Id to be matched exactly, same as an == search.</param> /// <returns>Null or an object matdhing the id.</returns> /// <exception cref="RealmClassLacksPrimaryKeyException">If the RealmObject class T lacks an [PrimaryKey].</exception> public T ObjectForPrimaryKey <T>(string id) where T : RealmObject { var metadata = Metadata[typeof(T).Name]; var rowPtr = NativeTable.RowForPrimaryKey(metadata.Table, metadata.PrimaryKeyColumnIndex, id); if (rowPtr == IntPtr.Zero) { return(null); } return((T)MakeObjectForRow(metadata, rowPtr)); }
protected void SetBooleanValue(string propertyName, bool value) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); if (!_realm.IsInTransaction) { throw new RealmOutsideTransactionException("Cannot set values outside transaction"); } var rowIndex = _rowHandle.RowIndex; NativeTable.set_bool(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, MarshalHelpers.BoolToIntPtr(value)); }
protected void SetInt64ValueUnique(string propertyName, long value) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); if (!_realm.IsInTransaction) { throw new RealmOutsideTransactionException("Cannot set values outside transaction"); } var rowIndex = _rowHandle.RowIndex; NativeTable.set_int64_unique(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, value); }
/// <summary> /// Fast count all objects of a given class, or in a RealmResults after casting. /// </summary> /// <remarks> /// Resolves to this method instead of the LINQ static extension <c>Count<T>(this IEnumerable<T>)</c>, when used directly on Realm.All. /// <br> /// if someone CASTS a RealmResults<T> variable from a Where call to /// a RealmResults<T> they change its compile-time type from IQueryable<blah> (which invokes LINQ) /// to RealmResults<T> and thus ends up here. /// </remarks> /// <returns>Count of all objects in a class or in the results of a search, without instantiating them.</returns> public int Count() { if (_allRecords) { // use the type captured at build based on generic T var tableHandle = _realm.Metadata [ObjectSchema.Name].Table; return((int)NativeTable.CountAll(tableHandle)); } // normally we would be in RealmQRealmResultsr.VisitMethodCall, not here // however, casting as described in the remarks above can cause this method to be invoked. // as in the unit test CountFoundWithCasting return((int)ResultsHandle.Count()); }
public static void SetObject(Realm realm, TableHandle table, IntPtr columnIndex, IntPtr rowIndex, RealmObject @object) { if (@object == null) { NativeTable.ClearLink(table, columnIndex, rowIndex); } else { if ([email protected]) { realm.Manage(@object); } NativeTable.SetLink(table, columnIndex, rowIndex, @object.RowHandle.RowIndex); } }
protected void SetDateTimeOffsetValue(string propertyName, DateTimeOffset value) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); if (!_realm.IsInTransaction) { throw new RealmOutsideTransactionException("Cannot set values outside transaction"); } var rowIndex = _rowHandle.RowIndex; var marshalledValue = value.ToUnixTimeSeconds(); NativeTable.set_datetime_seconds(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)rowIndex, marshalledValue); }
protected byte[] GetByteArrayValue(string propertyName) { Debug.Assert(_realm != null, "Object is not managed, but managed access was attempted"); int bufferSize; IntPtr buffer; if (NativeTable.get_binary(_metadata.Table, _metadata.ColumnIndices[propertyName], (IntPtr)_rowHandle.RowIndex, out buffer, out bufferSize) != IntPtr.Zero) { var bytes = new byte[bufferSize]; Marshal.Copy(buffer, bytes, 0, bufferSize); return(bytes); } return(null); }
/// <summary> /// Fast count all objects of a given class. /// </summary> /// <remarks> /// Resolves to this method instead of the LINQ static extension <c>Count<T>(this IEnumerable<T>)</c>, when used directly on Realm.All. /// </remarks> public int Count() { if (_allRecords) { // use the type captured at build based on generic T var tableHandle = _realm.Metadata[ElementType].Table; return((int)NativeTable.count_all(tableHandle)); } // normally we would be in RealmQRealmResultsr.VisitMethodCall, not here // however, if someone CASTS a RealmResults<blah> variable from a Where call to // a RealmResults<blah> they change its compile-time type from IQueryable<blah> (which invokes LINQ) // to RealmResults<blah> and thus ends up here. // as in the unit test CountFoundWithCasting return((int)NativeResults.count(ResultsHandle)); }
private QueryHandle CreateQuery(Schema.ObjectSchema elementType) { var tableHandle = _realm.Metadata[elementType.Name].Table; var queryHandle = tableHandle.TableWhere(); //At this point sh is invalid due to its handle being uninitialized, but the root is set correctly //a finalize at this point will not leak anything and the handle will not do anything //now, set the TableView handle... RuntimeHelpers.PrepareConstrainedRegions();//the following finally will run with no out-of-band exceptions try { } finally { queryHandle.SetHandle(NativeTable.Where(tableHandle)); }//at this point we have atomically acquired a handle and also set the root correctly so it can be unbound correctly return(queryHandle); }
internal LinkListHandle TableLinkList(IntPtr columnIndex, IntPtr rowIndex) { var listHandle = RootedLinkListHandle(); //At this point sh is invalid due to its handle being uninitialized, but the root is set correctly //a finalize at this point will not leak anything and the handle will not do anything //now, set the TableView handle... RuntimeHelpers.PrepareConstrainedRegions();//the following finally will run with no out-of-band exceptions try { } finally { listHandle.SetHandle(NativeTable.GetLinklist(this, columnIndex, rowIndex)); }//at this point we have atomically acquired a handle and also set the root correctly so it can be unbound correctly return(listHandle); }
internal QueryHandle TableWhere() { var queryHandle = RootedQueryHandle(); //At this point sh is invalid due to its handle being uninitialized, but the root is set correctly //a finalize at this point will not leak anything and the handle will not do anything //now, set the TableView handle... RuntimeHelpers.PrepareConstrainedRegions();//the following finally will run with no out-of-band exceptions try { } finally { queryHandle.SetHandle(NativeTable.Where(this)); }//at this point we have atomically acquired a handle and also set the root correctly so it can be unbound correctly return(queryHandle); }