Skip to content
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
6fe3aed
core updated to have new bison parser
LaPeste Jan 13, 2021
b73b62d
Wrong commit used for core
LaPeste Jan 14, 2021
ca13f01
New query was not applied on top of the previous one
LaPeste Jan 14, 2021
d3c4d48
PR feedback applied
LaPeste Jan 14, 2021
f30fad0
Forgot a null check
LaPeste Jan 14, 2021
67dfc41
Updated unit test to match changed in error message
LaPeste Jan 14, 2021
89ae7f5
Updated changelog
LaPeste Jan 14, 2021
6c827a5
Revert "Updated changelog"
LaPeste Jan 14, 2021
9533901
Updated changelog, again
LaPeste Jan 14, 2021
cfb927e
Fallback to original ordering if the new query doesn't have one
LaPeste Jan 14, 2021
cbc60cb
Fixed usage of query odering
LaPeste Jan 15, 2021
580699d
Updated unit test to use the user facing name of class
LaPeste Jan 15, 2021
b01db8c
Changed realm-core to have new changes
LaPeste Jan 15, 2021
0f49239
Core points to new commit
LaPeste Jan 15, 2021
0f0d18e
Updated changelog
LaPeste Jan 15, 2021
fd43ddb
Update CHANGELOG.md
LaPeste Jan 15, 2021
256369a
Update core submodule and added std::move
LaPeste Jan 18, 2021
37342c1
Added value substitution in string based query
LaPeste Jan 18, 2021
775bc51
All types have a unit test for string based search
LaPeste Jan 22, 2021
c9fc593
Changelog updated
LaPeste Jan 22, 2021
a63bd5c
Added object store to gitignore and set lf as ending line in code sty…
LaPeste Jan 22, 2021
0f0be4f
Changed style of object instantiation in array
LaPeste Jan 22, 2021
faf5d2b
Added unit test for in memory object in string based query
LaPeste Jan 22, 2021
6d06ad6
Renamed tests to be more coherent with the chosen style
LaPeste Jan 22, 2021
943be4f
Improved some code style
LaPeste Jan 22, 2021
e7ad03e
Added comment to explain PrimitiveValue <--> realm_value_t relationship
LaPeste Jan 25, 2021
0ad8d7d
Merge branch 'master' into ac/value-substitution-in-str-queries
LaPeste Jan 25, 2021
0a44eb5
Merge branch 'master' into ac/value-substitution-in-str-queries
LaPeste Jan 25, 2021
7a1fe0b
Renamed a var
LaPeste Jan 25, 2021
7ccc215
Fixed changelog and gitignore
LaPeste Jan 25, 2021
5ac3b31
Applied feedback from PR
LaPeste Jan 25, 2021
ea52b5e
Applied general feedback from PR
LaPeste Jan 27, 2021
0f6253c
Reshaped tests and added more
LaPeste Jan 29, 2021
eebf8e2
Merge branch 'master' into ac/value-substitution-in-str-queries
LaPeste Jan 29, 2021
d16127a
Point to right core and updated DictionaryHandle to respect signature…
LaPeste Jan 29, 2021
9d37a7c
Some renaming
LaPeste Feb 1, 2021
80fdbaf
Fixed changelog
LaPeste Feb 1, 2021
844ac8a
Some of the PR feedback applied
LaPeste Feb 1, 2021
4ba9d71
Simplified tests and added test for embedded objects and extended emb…
LaPeste Feb 4, 2021
c7e9790
Added RealmInteger tests for string query value sustitution
LaPeste Feb 4, 2021
41d3d02
Forgot to rethrow properly
LaPeste Feb 4, 2021
2050194
Test nullable null value correctly passed to core in query string val…
LaPeste Feb 4, 2021
65e1cf5
Small style fixes
LaPeste Feb 4, 2021
a98d164
Simplify boxing + add tostring overloads for test case data (#2228)
nirinchev Feb 4, 2021
10976dd
Reverted to correct core submodule to be equal to master
LaPeste Feb 5, 2021
a390ead
Fixed documentation for the Filter method
LaPeste Feb 5, 2021
37924d3
Merge branch 'master' into ac/value-substitution-in-str-queries
LaPeste Feb 17, 2021
7520217
Updated realm-core to fix unit test
LaPeste Feb 23, 2021
10cf0a4
Merge branch 'master' into ac/value-substitution-in-str-queries
LaPeste Feb 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ indent_style = space
tab_width = 4

# New line preferences
end_of_line = crlf
end_of_line = lf
insert_final_newline = false

#### .NET Coding Conventions ####
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
var obj = new MyObject();
obj.Denominations.Add("quarter", 0.25d);
```
* Added support for value substitution in string based queries. This enables expressions following [this syntax](https://github.com/realm/realm-js/blob/master/docs/tutorials/query-language.md): `realm.All<T>().Filter("field1 = $0 && field2 = $1", 123, "some-string-value")`. (Issue [#1822](https://github.com/realm/realm-dotnet/issues/1822))

### Compatibility
* Realm Studio: 10.0.0 or later.
Expand Down
4 changes: 2 additions & 2 deletions Realm/Realm/DatabaseTypes/RealmCollectionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ public T this[int index]
}
}

internal RealmResults<T> GetFilteredResults(string query)
internal RealmResults<T> GetFilteredResults(string query, RealmValue[] arguments)
{
var handle = Handle.Value.GetFilteredResults(query);
var handle = Handle.Value.GetFilteredResults(query, arguments);
return new RealmResults<T>(Realm, handle, Metadata);
}

Expand Down
7 changes: 5 additions & 2 deletions Realm/Realm/Extensions/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ public static IDisposable SubscribeForNotifications<T>(this IDictionary<string,
/// A Queryable collection, obtained by calling <see cref="Realm.All{T}"/>.
/// </param>
/// <param name="predicate">The predicate that will be applied.</param>
/// <param name="arguments">Values used for substitution in the predicate. Note that all primitive types are accepted as they are implicitly converted to RealmValue.</param>
/// <returns>A queryable observable collection of objects that match the predicate.</returns>
/// <remarks>
/// This method can be used in combination with LINQ filtering, but it is strongly recommended
Expand All @@ -210,16 +211,18 @@ public static IDisposable SubscribeForNotifications<T>(this IDictionary<string,
/// var results1 = realm.All&lt;Foo&gt;("Bar.IntValue > 0");
/// var results2 = realm.All&lt;Foo&gt;("Bar.IntValue > 0 SORT(Bar.IntValue ASC Bar.StringValue DESC)");
/// var results3 = realm.All&lt;Foo&gt;("Bar.IntValue > 0 SORT(Bar.IntValue ASC Bar.StringValue DESC) DISTINCT(Bar.IntValue)");
/// var results4 = realm.All&lt;Foo&gt;("Bar.IntValue > $0 || (Bar.String == $1 &amp;&amp; Bar.Bool == $2)" 5, "small", true");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// var results4 = realm.All&lt;Foo&gt;("Bar.IntValue > $0 || (Bar.String == $1 &amp;&amp; Bar.Bool == $2)" 5, "small", true");
/// var results4 = realm.All&lt;Foo&gt;("Bar.IntValue > $0 || (Bar.String == $1 &amp;&amp; Bar.Bool == $2)", 5, "small", true);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this posted only now? I do remember not seeing the suggestion after the talk in the call. Anyway, it's already fixed.

/// </code>
/// </example>
/// <seealso href="https://github.com/realm/realm-js/blob/master/docs/tutorials/query-language.md">
/// Examples of the NSPredicate syntax
/// </seealso>
/// <seealso href="https://academy.realm.io/posts/nspredicate-cheatsheet/">NSPredicate Cheatsheet</seealso>
public static IQueryable<T> Filter<T>(this IQueryable<T> query, string predicate)
public static IQueryable<T> Filter<T>(this IQueryable<T> query, string predicate, params RealmValue[] arguments)
{
Argument.NotNull(arguments, nameof(arguments));
var realmResults = Argument.EnsureType<RealmResults<T>>(query, $"{nameof(query)} must be a query obtained by calling Realm.All.", nameof(query));
return realmResults.GetFilteredResults(predicate);
return realmResults.GetFilteredResults(predicate, arguments);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you validate that arguments is not null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking to throw an exception (Argument.NotNull(obj, paramName)). Would that be fine or would you just return an empty result and let the dev figure out the why?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - Argument.NotNull sounds correct.

}

[EditorBrowsable(EditorBrowsableState.Never)]
Expand Down
2 changes: 1 addition & 1 deletion Realm/Realm/Handles/CollectionHandleBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public ResultsHandle Snapshot()
throw new NotSupportedException("Snapshotting this collection is not supported.");
}

public abstract ResultsHandle GetFilteredResults(string query);
public abstract ResultsHandle GetFilteredResults(string query, RealmValue[] arguments);

public abstract CollectionHandleBase Freeze(SharedRealmHandle frozenRealmHandle);

Expand Down
2 changes: 1 addition & 1 deletion Realm/Realm/Handles/DictionaryHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public override ThreadSafeReferenceHandle GetThreadSafeReference()
return new ThreadSafeReferenceHandle(result);
}

public override ResultsHandle GetFilteredResults(string query)
public override ResultsHandle GetFilteredResults(string query, RealmValue[] arguments)
{
throw new NotImplementedException("Dictionaries can't be filtered yet.");
}
Expand Down
2 changes: 1 addition & 1 deletion Realm/Realm/Handles/ListHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ public override ThreadSafeReferenceHandle GetThreadSafeReference()
return new ThreadSafeReferenceHandle(result);
}

public override ResultsHandle GetFilteredResults(string query)
public override ResultsHandle GetFilteredResults(string query, RealmValue[] arguments)
{
throw new NotImplementedException("Lists can't be filtered yet.");
}
Expand Down
21 changes: 18 additions & 3 deletions Realm/Realm/Handles/ResultsHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ private static class NativeMethods
public static extern IntPtr snapshot(ResultsHandle results, out NativeException ex);

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "results_get_filtered_results", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr get_filtered_results(ResultsHandle results, [MarshalAs(UnmanagedType.LPWStr)] string query_buf, IntPtr query_len, out NativeException ex);
public static extern IntPtr get_filtered_results(ResultsHandle results,
[MarshalAs(UnmanagedType.LPWStr)] string query_buf, IntPtr query_len,
[MarshalAs(UnmanagedType.LPArray), In] PrimitiveValue[] arguments, IntPtr args_count,
out NativeException ex);

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "results_find_object", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr find_object(ResultsHandle results, ObjectHandle objectHandle, out NativeException ex);
Expand Down Expand Up @@ -186,9 +189,21 @@ public override ThreadSafeReferenceHandle GetThreadSafeReference()
return new ThreadSafeReferenceHandle(result);
}

public override ResultsHandle GetFilteredResults(string query)
public override ResultsHandle GetFilteredResults(string query, RealmValue[] arguments)
{
var ptr = NativeMethods.get_filtered_results(this, query, (IntPtr)query.Length, out var ex);
var primitiveValues = new PrimitiveValue[arguments.Length];
var handles = new RealmValue.HandlesToCleanup?[arguments.Length];
for (var i = 0; i < arguments.Length; i++)
{
(primitiveValues[i], handles[i]) = arguments[i].ToNative();
}

var ptr = NativeMethods.get_filtered_results(this, query, (IntPtr)query.Length, primitiveValues, (IntPtr)primitiveValues.Length, out var ex);
foreach (var handle in handles)
{
handle?.Dispose();
}

ex.ThrowIfNecessary();
return new ResultsHandle(this, ptr);
}
Expand Down
2 changes: 1 addition & 1 deletion Realm/Realm/Handles/SetHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public override ThreadSafeReferenceHandle GetThreadSafeReference()
return new ThreadSafeReferenceHandle(result);
}

public override ResultsHandle GetFilteredResults(string query)
public override ResultsHandle GetFilteredResults(string query, RealmValue[] arguments)
{
throw new NotImplementedException("Sets can't be filtered yet.");
}
Expand Down
1 change: 1 addition & 0 deletions Realm/Realm/Native/PrimitiveValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

namespace Realms.Native
{
// This type is marshalled through C++ wrappers' realm_value_t
[StructLayout(LayoutKind.Explicit)]
[DebuggerDisplay("PrimitiveValue({Type})")]
internal unsafe struct PrimitiveValue
Expand Down
Loading