1+ namespace Simple . Data . QueryPolyfills
2+ {
3+ using System ;
4+ using System . Collections . Concurrent ;
5+ using System . Collections . Generic ;
6+ using System . Linq ;
7+
8+ class SelectClauseHandler
9+ {
10+ private readonly IList < SimpleReference > _references ;
11+ private readonly IList < ObjectReference > _objectReferences ;
12+ private readonly IList < FunctionReference > _functionReferences ;
13+ private Func < int , IDictionary < string , object > > _creator ;
14+
15+ public SelectClauseHandler ( SelectClause clause )
16+ {
17+ _references = clause . Columns . ToList ( ) ;
18+ _objectReferences = _references . Select ( r => r as ObjectReference ) . ToList ( ) ;
19+ _functionReferences = _references . Select ( r => r as FunctionReference ) . ToList ( ) ;
20+ }
21+
22+ public IEnumerable < IDictionary < string , object > > Run ( IEnumerable < IDictionary < string , object > > source )
23+ {
24+ return source . Select ( Run ) ;
25+ }
26+
27+ private IDictionary < string , object > Run ( IDictionary < string , object > source )
28+ {
29+ if ( _creator == null ) _creator = CreateCreator ( source ) ;
30+ var target = _creator ( _references . Count ) ;
31+ for ( int i = 0 ; i < _references . Count ; i ++ )
32+ {
33+ bool _ = TryCopyAsObjectReference ( _objectReferences [ i ] , source , target )
34+ || TryCopyAsFunctionReference ( _functionReferences [ i ] , source , target ) ;
35+ }
36+ return target ;
37+ }
38+
39+ private static bool TryCopyAsObjectReference ( ObjectReference reference , IDictionary < string , object > source , IDictionary < string , object > target )
40+ {
41+ if ( reference . IsNull ( ) ) return false ;
42+ target [ reference . GetAliasOrName ( ) ] = source [ reference . GetName ( ) ] ;
43+ return true ;
44+ }
45+
46+ private static bool TryCopyAsFunctionReference ( FunctionReference reference , IDictionary < string , object > source , IDictionary < string , object > target )
47+ {
48+ if ( reference . IsNull ( ) ) return false ;
49+ var argument = ( ObjectReference ) reference . Argument ;
50+ target [ reference . GetAliasOrName ( ) ] = ApplyFunction ( reference , source [ argument . GetName ( ) ] ) ;
51+ return true ;
52+ }
53+
54+ private static object ApplyFunction ( FunctionReference function , object value )
55+ {
56+ if ( function . Name . Equals ( "length" , StringComparison . OrdinalIgnoreCase ) )
57+ {
58+ return value == null ? 0 : value . ToString ( ) . Length ;
59+ }
60+ return value ;
61+ }
62+
63+ private Func < int , IDictionary < string , object > > CreateCreator ( IDictionary < string , object > source )
64+ {
65+ var dictionary = source as Dictionary < string , object > ;
66+ if ( dictionary != null ) return cap => new Dictionary < string , object > ( cap , dictionary . Comparer ) ;
67+ var sortedDictionary = source as SortedDictionary < string , object > ;
68+ if ( sortedDictionary != null ) return cap => new SortedDictionary < string , object > ( sortedDictionary . Comparer ) ;
69+ var concurrentDictionary = source as ConcurrentDictionary < string , object > ;
70+ if ( concurrentDictionary != null ) return cap => new ConcurrentDictionary < string , object > ( ) ;
71+
72+ var type = source . GetType ( ) ;
73+ return cap => ( IDictionary < string , object > ) Activator . CreateInstance ( type ) ;
74+ }
75+ }
76+ }
0 commit comments