22using Hi3Helper . SentryHelper ;
33using Libsql . Client ;
44using System ;
5+ using System . Collections . Generic ;
56using System . Diagnostics ;
67using System . Linq ;
78using System . Text ;
@@ -29,7 +30,7 @@ public static bool? IsEnabled
2930 field = value ;
3031 DbConfig . DbEnabled = value ?? false ;
3132
32- _isFirstInit = true ; // Force first init
33+ IsInitialized = false ; // Force first init
3334 if ( ! ( value ?? false ) ) Dispose ( ) ; // Dispose instance if user disabled database function globally
3435 }
3536 }
@@ -45,11 +46,11 @@ public static string? Uri
4546 }
4647 set
4748 {
48- if ( value != field ) _isFirstInit = true ; // Force first init if value changed
49+ if ( value != field ) IsInitialized = false ; // Force first init if value changed
4950
5051 field = value ;
5152 DbConfig . DbUrl = value ;
52- _isFirstInit = true ;
53+ IsInitialized = false ;
5354 }
5455 }
5556
@@ -65,11 +66,11 @@ public static string? Token
6566 }
6667 set
6768 {
68- if ( value != field ) _isFirstInit = true ; // Force first init if value changed
69+ if ( value != field ) IsInitialized = false ; // Force first init if value changed
6970
7071 field = value ;
7172 DbConfig . DbToken = value ;
72- _isFirstInit = true ;
73+ IsInitialized = false ;
7374 }
7475 }
7576
@@ -93,25 +94,26 @@ public static string? UserId
9394 }
9495 set
9596 {
96- if ( value != field ) _isFirstInit = true ; // Force first init if value changed
97+ if ( value != field ) IsInitialized = false ; // Force first init if value changed
9798
9899 field = value ;
99100 DbConfig . UserGuid = value ;
100101
101102 if ( string . IsNullOrWhiteSpace ( value ) )
102103 {
103104 _userIdHash = null ;
104- _isFirstInit = true ;
105+ IsInitialized = false ;
105106 return ;
106107 }
107108
108109 var byteUidH = System . IO . Hashing . XxHash64 . Hash ( Encoding . ASCII . GetBytes ( value ) ) ;
109110 _userIdHash = Convert . ToHexStringLower ( byteUidH ) ;
110- _isFirstInit = true ;
111+ IsInitialized = false ;
111112 }
112113 }
114+
115+ public static bool IsInitialized { get ; private set ; } = false ;
113116
114- private static bool _isFirstInit = true ;
115117 #endregion
116118
117119 [ DebuggerBrowsable ( DebuggerBrowsableState . Never ) ]
@@ -156,14 +158,18 @@ public static async Task Init(bool redirectThrow = false, bool bypassEnableFlag
156158 opts . AuthToken = Token ;
157159 } ) ;
158160
159- if ( _isFirstInit )
161+ if ( ! IsInitialized )
160162 {
161163 LogWriteLine ( "[DbHandler::Init] Initializing database system..." ) ;
162164 // Ensure table exist at first initialization
163165 await
164166 _database
165167 . Execute ( $ "CREATE TABLE IF NOT EXISTS \" uid-{ _userIdHash } \" (Id INTEGER PRIMARY KEY AUTOINCREMENT, 'key' TEXT UNIQUE NOT NULL, 'value' TEXT)") ;
166- _isFirstInit = false ;
168+
169+ await
170+ _database
171+ . Execute ( $ "CREATE TABLE IF NOT EXISTS \" uid-{ _userIdHash } -blob\" (Id INTEGER PRIMARY KEY AUTOINCREMENT, 'key' TEXT UNIQUE NOT NULL, 'value' BLOB)") ;
172+ IsInitialized = true ;
167173 }
168174 else LogWriteLine ( "[DbHandler::Init] Reinitializing database system..." ) ;
169175 }
@@ -218,7 +224,7 @@ private static void Dispose()
218224
219225 private const int MaxAttempts = 5 ;
220226
221- public static async Task < string ? > QueryKey ( string key , bool redirectThrow = false )
227+ public static async Task < string ? > QueryKey ( string key , bool redirectThrow = false , bool isBlob = false )
222228 {
223229 if ( ! ( IsEnabled ?? false ) ) return null ;
224230 #if DEBUG
@@ -229,16 +235,24 @@ private static void Dispose()
229235 #endif
230236 for ( var i = 0 ; i < MaxAttempts ; i ++ )
231237 {
232- var retVal = await QueryKeyInternal ( key
238+ var retVal = await QueryKeyInternal ( key , isBlob
233239 #if DEBUG
234240 , sId
235241 #endif
236242 ) ;
237243 if ( retVal . result == 200 )
238244 {
239245 #if DEBUG
240- LogWriteLine ( $ "[DBHandler::QueryKey][{ sId } ] Got value!\r \n \t Key: { key } \r \n \t Value:\r \n { retVal . returnedValue } ",
241- LogType . Debug , true ) ;
246+ if ( isBlob )
247+ {
248+ LogWriteLine ( $ "[DBHandler::QueryKey][{ sId } ] Got value!\r \n \t Key: { key } \r \n \t IS BLOB",
249+ LogType . Debug , true ) ;
250+ }
251+ else
252+ {
253+ LogWriteLine ( $ "[DBHandler::QueryKey][{ sId } ] Got value!\r \n \t Key: { key } \r \n \t Value:\r \n { retVal . returnedValue } ",
254+ LogType . Debug , true ) ;
255+ }
242256 #endif
243257 return retVal . returnedValue ;
244258 }
@@ -278,24 +292,43 @@ private static void Dispose()
278292 return null ;
279293 }
280294
281- public static async Task StoreKeyValue ( string key , string value , bool redirectThrow = false )
295+ public static async Task StoreKeyValue ( string key , string value , bool redirectThrow = false ,
296+ bool isBlob = false , byte [ ] ? blobValue = null )
282297 {
283298 if ( ! ( IsEnabled ?? false ) ) return ;
284299 #if DEBUG
285300 var t = Stopwatch . StartNew ( ) ;
286301 var r = new Random ( ) ;
287302 var sId = Math . Abs ( r . Next ( 0 , 1000 ) . ToString ( ) . GetHashCode ( ) ) ;
288- LogWriteLine ( $ "[DBHandler::StoreKeyValue][{ sId } ] Invoked!\r \n \t Key: { key } \r \n \t Value: { value } ", LogType . Debug ,
289- true ) ;
303+ if ( isBlob )
304+ {
305+ LogWriteLine ( $ "[DBHandler::StoreKeyValue][{ sId } ] Invoked!\r \n \t Key: { key } \r \n \t IS BLOB", LogType . Debug ,
306+ true ) ;
307+ }
308+ else
309+ {
310+ LogWriteLine ( $ "[DBHandler::StoreKeyValue][{ sId } ] Invoked!\r \n \t Key: { key } \r \n \t Value: { value } ", LogType . Debug ,
311+ true ) ;
312+ }
313+
290314 #endif
291315 for ( var i = 0 ; i < MaxAttempts ; i ++ )
292316 {
293- var retVal = await StoreKeyValueInternal ( key , value ) ;
317+ var retVal = await StoreKeyValueInternal ( key , value , isBlob , blobValue ) ;
294318 if ( retVal . result == 200 )
295319 {
296320 #if DEBUG
297- LogWriteLine ( $ "[DBHandler::StoreKeyValue][{ sId } ] Saved value!\r \n \t Key: { key } \r \n \t Value: { value } ",
298- LogType . Debug , true ) ;
321+ if ( isBlob )
322+ {
323+ LogWriteLine ( $ "[DBHandler::StoreKeyValue][{ sId } ] Saved value!\r \n \t Key: { key } \r \n \t IS BLOB",
324+ LogType . Debug , true ) ;
325+ }
326+ else
327+ {
328+ LogWriteLine ( $ "[DBHandler::StoreKeyValue][{ sId } ] Saved value!\r \n \t Key: { key } \r \n \t Value: { value } ",
329+ LogType . Debug , true ) ;
330+ }
331+
299332 #endif
300333 return ;
301334 }
@@ -338,7 +371,7 @@ public static async Task StoreKeyValue(string key, string value, bool redirectTh
338371
339372 #region Private Methods
340373
341- private static async Task < ( int result , string ? returnedValue , Exception ? exceptionValue ) > QueryKeyInternal ( string key
374+ private static async Task < ( int result , string ? returnedValue , Exception ? exceptionValue ) > QueryKeyInternal ( string key , bool isBlob
342375 #if DEBUG
343376 , int sId = 0
344377 #endif
@@ -347,22 +380,53 @@ public static async Task StoreKeyValue(string key, string value, bool redirectTh
347380 try
348381 {
349382 if ( _database == null ) await Init ( true ) ;
383+ var tableName = "uid-" + _userIdHash + ( isBlob ? "-blob" : "" ) ;
350384 // Get table row for exact key
351385 var rs =
352386 await
353387 _database !
354- . Execute ( $ "SELECT value FROM \" uid- { _userIdHash } \" WHERE key = ?", key ) ;
388+ . Execute ( $ "SELECT value FROM \" { tableName } \" WHERE key = ?", key ) ;
355389 if ( rs == null )
356390 {
357391 return ( 200 , null , null ) ;
358392 }
393+
394+ string str = "" ;
359395
360- // freaking black magic to convert the column row to the value
361- var str =
362- string . Join ( "" , rs . Rows . Select ( row => string . Join ( "" , row . Select ( x => x . ToString ( ) ) ) ) ) ;
396+ if ( isBlob )
397+ {
398+ var firstRow = rs . Rows . FirstOrDefault ( ) ;
399+ object ? rcv = firstRow ? . FirstOrDefault ( ) ;
400+
401+ if ( rcv is Blob { Value : IEnumerable < byte > byteEnumerable } )
402+ {
403+ str = Convert . ToHexString ( byteEnumerable . ToArray ( ) ) ;
404+ }
405+ // ReSharper disable once ConvertTypeCheckPatternToNullCheck
406+ else if ( rcv is Blob { Value : byte [ ] directBytes } )
407+ {
408+ str = Convert . ToHexString ( directBytes ) ;
409+ }
410+ }
411+ else
412+ {
413+ // freaking black magic to convert the column row to the value
414+ str =
415+ string . Join ( "" , rs . Rows . Select ( row => string . Join ( "" , row . Select ( x => x . ToString ( ) ) ) ) ) ;
416+ }
417+
363418 #if DEBUG
364- LogWriteLine ( $ "[DBHandler::QueryKey][{ sId } ] Got value!\r \n \t Key: { key } \r \n \t Value:\r \n { str } ", LogType . Debug ,
365- true ) ;
419+ if ( isBlob )
420+ {
421+ LogWriteLine ( $ "[DBHandler::QueryKey][{ sId } ] Got value!\r \n \t Key: { key } \r \n \t IS BLOB", LogType . Debug ,
422+ true ) ;
423+ }
424+ else
425+ {
426+ LogWriteLine ( $ "[DBHandler::QueryKey][{ sId } ] Got value!\r \n \t Key: { key } \r \n \t Value:\r \n { str } ", LogType . Debug ,
427+ true ) ;
428+ }
429+
366430 #endif
367431 return ( 200 , str , null ) ; // 200: OK, return value
368432 }
@@ -386,16 +450,18 @@ public static async Task StoreKeyValue(string key, string value, bool redirectTh
386450 }
387451 }
388452
389- private static async Task < ( int result , Exception ? exceptionValue ) > StoreKeyValueInternal ( string key , string value )
453+ private static async Task < ( int result , Exception ? exceptionValue ) > StoreKeyValueInternal ( string key , string value , bool isBlob = false , byte [ ] ? blobValue = null )
390454 {
391455 try
392456 {
393457 if ( _database == null ) await Init ( true ) ;
458+ var tableName = "uid-" + _userIdHash + ( isBlob ? "-blob" : "" ) ;
459+ object dbValue = isBlob && blobValue != null ? blobValue : value ;
394460
395461 // Create key for storing value, if key already exist, just update the value (key column is set to UNIQUE)
396- var command = $ "INSERT INTO \" uid- { _userIdHash } \" (key, value) VALUES (?, ?) " +
462+ var command = $ "INSERT INTO \" { tableName } \" (key, value) VALUES (?, ?) " +
397463 $ "ON CONFLICT(key) DO UPDATE SET value = ?";
398- var parameters = new object [ ] { key , value , value } ;
464+ var parameters = new object [ ] { key , dbValue , dbValue } ;
399465 await _database ! . Execute ( command , parameters ) ;
400466
401467 return ( 200 , null ) ; // 200: OK
0 commit comments