@@ -10,6 +10,7 @@ namespace LcmCrdt.Data;
1010public class CustomSqliteFunctionInterceptor : IDbConnectionInterceptor , IConnectionInterceptor
1111{
1212 public const string ContainsFunction = "contains" ;
13+ public const string StartsWithFunction = "startsWith" ;
1314
1415 public void ConnectionOpened ( DbConnection connection , ConnectionEndEventData eventData )
1516 {
@@ -49,15 +50,13 @@ private void ConnectionOpened(DbConnection connection)
4950 {
5051 if ( connection is SqliteConnection sqliteConnection )
5152 {
52- RegisterContainsFunction ( sqliteConnection ) ;
53+ RegisterCustomFunctions ( sqliteConnection ) ;
5354 }
5455 }
5556
56- public static void RegisterContainsFunction ( SqliteConnection sqliteConnection )
57+ public static void RegisterCustomFunctions ( SqliteConnection sqliteConnection )
5758 {
58- //creates a new function that can be used in queries
5959 sqliteConnection . CreateFunction ( ContainsFunction ,
60- //in sqlite strings are byte arrays, so we can avoid allocating strings by using spans
6160 ( byte [ ] ? str , byte [ ] ? value ) =>
6261 {
6362 if ( str is null || value is null ) return false ;
@@ -66,13 +65,29 @@ public static void RegisterContainsFunction(SqliteConnection sqliteConnection)
6665 Span < char > search = stackalloc char [ Encoding . UTF8 . GetCharCount ( value ) ] ;
6766 Encoding . UTF8 . GetChars ( str , source ) ;
6867 Encoding . UTF8 . GetChars ( value , search ) ;
69- return CultureInfo . InvariantCulture . CompareInfo . IndexOf ( source ,
70- search ,
71- ContainsDiacritic ( search )
72- ? CompareOptions . IgnoreCase
73- : CompareOptions . IgnoreNonSpace | CompareOptions . IgnoreCase
74- ) >= 0 ;
68+ var options = DiacriticMatchOptions ( search ) ;
69+ return CultureInfo . InvariantCulture . CompareInfo . IndexOf ( source , search , options ) >= 0 ;
7570 } ) ;
71+
72+ sqliteConnection . CreateFunction ( StartsWithFunction ,
73+ ( byte [ ] ? str , byte [ ] ? value ) =>
74+ {
75+ if ( str is null || value is null ) return false ;
76+
77+ Span < char > source = stackalloc char [ Encoding . UTF8 . GetCharCount ( str ) ] ;
78+ Span < char > search = stackalloc char [ Encoding . UTF8 . GetCharCount ( value ) ] ;
79+ Encoding . UTF8 . GetChars ( str , source ) ;
80+ Encoding . UTF8 . GetChars ( value , search ) ;
81+ var options = DiacriticMatchOptions ( search ) ;
82+ return CultureInfo . InvariantCulture . CompareInfo . IsPrefix ( source , search , options ) ;
83+ } ) ;
84+ }
85+
86+ private static CompareOptions DiacriticMatchOptions ( in ReadOnlySpan < char > search )
87+ {
88+ return ContainsDiacritic ( search )
89+ ? CompareOptions . IgnoreCase
90+ : CompareOptions . IgnoreCase | CompareOptions . IgnoreNonSpace ;
7691 }
7792
7893 private static bool ContainsDiacritic ( in ReadOnlySpan < char > value )
0 commit comments