Custom Query Comparator

Db4o allows using a custom comparator for query processing. This can be useful for replacing the standard way of selecting query results, for example, when a non-standard attribute type should be compared as string or integer

The usage is best shown on an example.

Let's create a custom class containing string information:

MyString.cs
01/* Copyright (C) 2007 db4objects Inc. http://www.db4o.com */ 02namespace Db4objects.Db4odoc.Comparing 03{ 04 class MyString 05 { 06 private string _string; 07 08 public MyString(string str){ 09 _string = str; 10 } 11 12 public override string ToString(){ 13 return _string; 14 } 15 } 16}

MyString.vb
01' Copyright (C) 2007 db4objects Inc. http://www.db4o.com 02Namespace Db4objects.Db4odoc.Comparing 03 04 Class MyString 05 Private _string As String 06 07 Public Sub New(ByVal str As String) 08 _string = str 09 End Sub 10 11 Public Overloads Overrides Function ToString() As String 12 Return _string 13 End Function 14 End Class 15End Namespace

MyString class will be used for an attribute in the following class:

Record.cs
01/* Copyright (C) 2007 db4objects Inc. http://www.db4o.com */ 02namespace Db4objects.Db4odoc.Comparing 03{ 04 class Record 05 { 06 private MyString _record; 07 08 09 public Record(string record) 10 { 11 _record = new MyString(record); 12 } 13 14 public override string ToString() 15 { 16 return _record.ToString(); 17 } 18 } 19}

Record.vb
01' Copyright (C) 2007 db4objects Inc. http://www.db4o.com 02Namespace Db4objects.Db4odoc.Comparing 03 04 Class Record 05 Private _record As MyString 06 07 Public Sub New(ByVal record As String) 08 _record = New MyString(record) 09 End Sub 10 11 Public Overloads Overrides Function ToString() As String 12 Return _record.ToString 13 End Function 14 End Class 15End Namespace

Let's save some Record objects to the database:

CompareExample.cs: StoreRecords
01private static void StoreRecords(IConfiguration configuration) 02 { 03 File.Delete(FileName); 04 IObjectContainer container = Db4oFactory.OpenFile(configuration, FileName); 05 try 06 { 07 Record record = new Record("Michael Schumacher, points: 100"); 08 container.Set(record); 09 record = new Record("Rubens Barrichello, points: 98"); 10 container.Set(record); 11 record = new Record("Kimi Raikonnen, points: 55"); 12 container.Set(record); 13 } 14 finally 15 { 16 container.Close(); 17 } 18 }

CompareExample.vb: StoreRecords
01Public Shared Sub StoreRecords(ByVal configuration As IConfiguration) 02 File.Delete(FileName) 03 Dim container As IObjectContainer = Db4oFactory.OpenFile(configuration, FileName) 04 Try 05 Dim record As Record = New Record("Michael Schumacher, points: 100") 06 container.Set(record) 07 record = New Record("Rubens Barrichello, points: 98") 08 container.Set(record) 09 record = New Record("Kimi Raikonnen, points: 55") 10 container.Set(record) 11 Finally 12 container.Close() 13 End Try 14 End Sub

Selecting the query results, we need to compare string values contained in MyString objects. This can be configured with the following setting:

CompareExample.cs: Configure
1private static IConfiguration Configure() 2 { 3 IConfiguration configuration = Db4oFactory.NewConfiguration(); 4 configuration.ObjectClass(typeof(MyString)).Compare(new MyStringAttribute()); 5 return configuration; 6 }
CompareExample.cs: MyStringAttribute
01private class MyStringAttribute : IObjectAttribute 02 { 03 public object Attribute(object original) 04 { 05 if (original is MyString) 06 { 07 return ((MyString)original).ToString(); 08 } 09 return original; 10 } 11 }

CompareExample.vb: Configure
1Public Shared Function Configure() As IConfiguration 2 Dim configuration As IConfiguration = Db4oFactory.NewConfiguration() 3 configuration.ObjectClass(GetType(MyString)).Compare(New MyStringAttribute) 4 Return configuration 5 End Function
CompareExample.vb: MyStringAttribute
01Private Class MyStringAttribute 02 Implements IObjectAttribute 03 04 Public Function Attribute(ByVal original As Object) As Object Implements IObjectAttribute.Attribute 05 If TypeOf original Is MyString Then 06 Return CType(original, MyString).ToString 07 End If 08 Return original 09 End Function 10 End Class
 

This piece of code registers an attribute provider for special query behavior.

The query processor will compare the object returned by the attribute provider instead of the actual object, both for the constraint and the candidate persistent object.

The querying code will look like this:

CompareExample.cs: CheckRecords
01private static void CheckRecords(IConfiguration configuration) 02 { 03 IObjectContainer container = Db4oFactory.OpenFile(configuration, FileName); 04 try 05 { 06 IQuery q = container.Query(); 07 q.Constrain(new Record("Rubens")); 08 q.Descend("_record").Constraints().Contains(); 09 IObjectSet result = q.Execute(); 10 ListResult(result); 11 } 12 finally 13 { 14 container.Close(); 15 } 16 }

CompareExample.vb: CheckRecords
01Public Shared Sub CheckRecords(ByVal configuration As IConfiguration) 02 Dim container As IObjectContainer = Db4oFactory.OpenFile(configuration, FileName) 03 Try 04 Dim q As IQuery = container.Query 05 q.Constrain(New Record("Rubens")) 06 q.Descend("_record").Constraints.Contains() 07 Dim result As IObjectSet = q.Execute 08 ListResult(result) 09 Finally 10 container.Close() 11 End Try 12 End Sub

Using query comparator feature we can change the standard way of selecting query results. This can be helpful for:

  • querying user types using simple string or numeric representation
  • encapsulating additional logic into querying algorithm.