@@ -22,13 +22,13 @@ internal SqlitePlugin(IGuidProvider guidProvider, IReflectionGuard reflectionGua
2222 _reflectionGuard = reflectionGuard ?? throw new ArgumentNullException ( nameof ( reflectionGuard ) ) ;
2323 }
2424
25- public PluginMetadata Metadata => new PluginMetadata
25+ public PluginMetadata Metadata => new ( )
2626 {
2727 Id = Guid . Parse ( "6457ab5d-0487-4c06-a313-1ebf789f2b52" ) ,
2828 Name = "Sqlite" ,
2929 CompanyName = "FlowSynx" ,
3030 Description = Resources . PluginDescription ,
31- Version = new Version ( 1 , 1 , 1 ) ,
31+ Version = new Version ( 1 , 2 , 0 ) ,
3232 Category = PluginCategory . Database ,
3333 Authors = new List < string > { "FlowSynx" } ,
3434 Copyright = "© FlowSynx. All rights reserved." ,
@@ -44,21 +44,24 @@ internal SqlitePlugin(IGuidProvider guidProvider, IReflectionGuard reflectionGua
4444
4545 public Type SpecificationsType => typeof ( SqlitePluginSpecifications ) ;
4646
47- private Dictionary < string , Func < InputParameter , CancellationToken , Task < object ? > > > OperationMap => new ( StringComparer . OrdinalIgnoreCase )
48- {
49- [ "query" ] = async ( parameters , cancellationToken ) => await ExecuteQueryAsync ( parameters , cancellationToken ) ,
50- [ "execute" ] = async ( parameters , cancellationToken ) => { await ExecuteNonQueryAsync ( parameters , cancellationToken ) ; return null ; }
51- } ;
47+ private Dictionary < string , Func < InputParameter , CancellationToken , Task < object ? > > > OperationMap =>
48+ new Dictionary < string , Func < InputParameter , CancellationToken , Task < object ? > > > ( StringComparer . OrdinalIgnoreCase )
49+ {
50+ [ "query" ] = async ( p , t ) => await ExecuteQueryAsync ( p , t ) ,
51+ [ "execute" ] = async ( p , t ) => { await ExecuteNonQueryAsync ( p , t ) ; return null ; }
52+ } ;
5253
5354 public IReadOnlyCollection < string > SupportedOperations => OperationMap . Keys ;
5455
5556 public Task Initialize ( IPluginLogger logger )
5657 {
5758 ThrowIfReflection ( ) ;
5859 ArgumentNullException . ThrowIfNull ( logger ) ;
60+
5961 _sqliteSpecifications = Specifications . ToObject < SqlitePluginSpecifications > ( ) ;
6062 _logger = logger ;
6163 _isInitialized = true ;
64+
6265 return Task . CompletedTask ;
6366 }
6467
@@ -68,108 +71,114 @@ public Task Initialize(IPluginLogger logger)
6871 ThrowIfReflection ( ) ;
6972 ThrowIfNotInitialized ( ) ;
7073
71- var inputParameter = parameters . ToObject < InputParameter > ( ) ;
72- var operation = inputParameter . Operation ;
73-
74- if ( OperationMap . TryGetValue ( operation , out var handler ) )
75- {
76- return await handler ( inputParameter , cancellationToken ) ;
77- }
74+ var input = parameters . ToObject < InputParameter > ( ) ;
75+ if ( ! OperationMap . TryGetValue ( input . Operation , out var handler ) )
76+ throw new NotSupportedException ( $ "Sqlite plugin: Operation '{ input . Operation } ' is not supported.") ;
7877
79- throw new NotSupportedException ( $ "Sqlite plugin: Operation ' { operation } ' is not supported." ) ;
78+ return await handler ( input , cancellationToken ) ;
8079 }
8180
82- private void ThrowIfReflection ( )
83- {
84- if ( _reflectionGuard . IsCalledViaReflection ( ) )
85- throw new InvalidOperationException ( Resources . ReflectionBasedAccessIsNotAllowed ) ;
86- }
87-
88- private void ThrowIfNotInitialized ( )
89- {
90- if ( ! _isInitialized )
91- throw new InvalidOperationException ( $ "Plugin '{ Metadata . Name } ' v{ Metadata . Version } is not initialized.") ;
92- }
81+ #region private methods
9382
94- private async Task ExecuteNonQueryAsync ( InputParameter parameters , CancellationToken cancellationToken )
83+ private async Task ExecuteNonQueryAsync ( InputParameter input , CancellationToken token )
9584 {
96- var ( sql , sqlParams ) = GetSqlAndParameters ( parameters ) ;
85+ var ( sql , sqlParams ) = ExtractSqlParameters ( input ) ;
86+ var connectionString = _sqliteSpecifications . ConnectionString ;
9787
9888 try
9989 {
100- var connection = new SqliteConnection ( _sqliteSpecifications . ConnectionString ) ;
101- await connection . OpenAsync ( ) ;
102- using var cmd = new SqliteCommand ( parameters . Sql , connection ) ;
90+ await using var connection = new SqliteConnection ( connectionString ) ;
91+ await connection . OpenAsync ( token ) ;
10392
104- AddParameters ( cmd , sqlParams ) ;
105-
106- cancellationToken . ThrowIfCancellationRequested ( ) ;
93+ var context = ParseInputData ( input . Data ) ;
10794
108- int affectedRows = await cmd . ExecuteNonQueryAsync ( cancellationToken ) ;
109- _logger ? . LogInfo ( $ "Non-query executed successfully. Rows affected: { affectedRows } .") ;
95+ if ( context . StructuredData ? . Count > 0 )
96+ {
97+ await ExecuteStructuredDataAsync ( connection , sql , context , token ) ;
98+ }
99+ else
100+ {
101+ await ExecuteSingleNonQueryAsync ( connection , sql , sqlParams , token ) ;
102+ }
110103 }
111104 catch ( Exception ex )
112105 {
113- _logger ? . LogError ( $ "Error executing Sqlite sql statement. Error : { ex . Message } ") ;
106+ _logger ? . LogError ( $ "Error executing Sqlite SQL statement: { ex . Message } ") ;
114107 throw ;
115108 }
116109 }
117110
118- private async Task < PluginContext > ExecuteQueryAsync ( InputParameter parameters , CancellationToken cancellationToken )
111+ private async Task < PluginContext > ExecuteQueryAsync ( InputParameter input , CancellationToken token )
119112 {
120- var ( sql , sqlParams ) = GetSqlAndParameters ( parameters ) ;
113+ var ( sql , sqlParams ) = ExtractSqlParameters ( input ) ;
114+ var connectionString = _sqliteSpecifications . ConnectionString ;
121115
122116 try
123117 {
124118 var result = new List < Dictionary < string , object > > ( ) ;
125- var connection = new SqliteConnection ( _sqliteSpecifications . ConnectionString ) ;
126- await connection . OpenAsync ( ) ;
127- using var cmd = new SqliteCommand ( sql , connection ) ;
119+ await using var connection = new SqliteConnection ( connectionString ) ;
120+ await connection . OpenAsync ( token ) ;
128121
122+ await using var cmd = new SqliteCommand ( sql , connection ) ;
129123 AddParameters ( cmd , sqlParams ) ;
130124
131- cancellationToken . ThrowIfCancellationRequested ( ) ;
132-
133- using var reader = await cmd . ExecuteReaderAsync ( cancellationToken ) ;
134-
135- while ( await reader . ReadAsync ( cancellationToken ) )
125+ await using var reader = await cmd . ExecuteReaderAsync ( token ) ;
126+ while ( await reader . ReadAsync ( token ) )
136127 {
137- var row = new Dictionary < string , object > ( ) ;
138- for ( int i = 0 ; i < reader . FieldCount ; i ++ )
139- {
140- row [ reader . GetName ( i ) ] = reader . GetValue ( i ) ;
141- }
128+ var row = Enumerable . Range ( 0 , reader . FieldCount )
129+ . ToDictionary ( reader . GetName , reader . GetValue ) ;
142130 result . Add ( row ) ;
143131 }
144132
145133 _logger ? . LogInfo ( $ "Query executed successfully. Rows returned: { result . Count } .") ;
146- string key = $ " { _guidProvider . NewGuid ( ) } " ;
147- return new PluginContext ( key , "Data" )
134+
135+ return new PluginContext ( _guidProvider . NewGuid ( ) . ToString ( ) , "Data" )
148136 {
149137 Format = "Database" ,
150138 StructuredData = result
151139 } ;
152140 }
153141 catch ( Exception ex )
154142 {
155- _logger ? . LogError ( $ "Error executing Sqlite sql statement. Error : { ex . Message } ") ;
143+ _logger ? . LogError ( $ "Error executing Sqlite query : { ex . Message } ") ;
156144 throw ;
157145 }
158146 }
159147
160- private ( string Sql , Dictionary < string , object > Parameters ) GetSqlAndParameters ( InputParameter parameters )
148+ private async Task ExecuteStructuredDataAsync (
149+ SqliteConnection connection , string sql , PluginContext context , CancellationToken token )
161150 {
162- if ( string . IsNullOrEmpty ( parameters . Sql ) )
163- throw new ArgumentException ( "Missing 'sql' parameter." ) ;
164-
165- Dictionary < string , object > sqlParams = new ( ) ;
151+ int totalAffected = 0 ;
166152
167- if ( parameters . Params is Dictionary < string , object > paramDict )
153+ if ( context . StructuredData is not null )
168154 {
169- sqlParams = paramDict ;
155+ foreach ( var row in context . StructuredData )
156+ {
157+ await using var cmd = new SqliteCommand ( sql , connection ) ;
158+ AddParameters ( cmd , row ) ;
159+ totalAffected += await cmd . ExecuteNonQueryAsync ( token ) ;
160+ }
170161 }
171162
172- return ( parameters . Sql , sqlParams ) ;
163+ _logger ? . LogInfo ( $ "Executed structured SQL for { context . StructuredData ? . Count } rows. Total affected: { totalAffected } ") ;
164+ }
165+
166+ private async Task ExecuteSingleNonQueryAsync (
167+ SqliteConnection connection , string sql , Dictionary < string , object > sqlParams , CancellationToken token )
168+ {
169+ await using var cmd = new SqliteCommand ( sql , connection ) ;
170+ AddParameters ( cmd , sqlParams ) ;
171+ int affected = await cmd . ExecuteNonQueryAsync ( token ) ;
172+ _logger ? . LogInfo ( $ "Non-query executed successfully. Rows affected: { affected } .") ;
173+ }
174+
175+ private ( string Sql , Dictionary < string , object > Params ) ExtractSqlParameters ( InputParameter input )
176+ {
177+ if ( string . IsNullOrWhiteSpace ( input . Sql ) )
178+ throw new ArgumentException ( "Missing 'sql' parameter." ) ;
179+
180+ var sqlParams = input . Params as Dictionary < string , object > ?? new ( ) ;
181+ return ( input . Sql , sqlParams ) ;
173182 }
174183
175184 private void AddParameters ( SqliteCommand cmd , Dictionary < string , object > ? parameters )
@@ -226,4 +235,31 @@ private void AddParameters(SqliteCommand cmd, Dictionary<string, object>? parame
226235 }
227236 }
228237 }
238+
239+ private PluginContext ParseInputData ( object ? data )
240+ {
241+ if ( data is null )
242+ throw new ArgumentNullException ( nameof ( data ) , "Input data cannot be null." ) ;
243+
244+ return data switch
245+ {
246+ PluginContext context => context ,
247+ IEnumerable < PluginContext > => throw new NotSupportedException ( "List of PluginContext is not supported." ) ,
248+ _ => throw new NotSupportedException ( "Unsupported input data format." )
249+ } ;
250+ }
251+
252+ private void ThrowIfReflection ( )
253+ {
254+ if ( _reflectionGuard . IsCalledViaReflection ( ) )
255+ throw new InvalidOperationException ( Resources . ReflectionBasedAccessIsNotAllowed ) ;
256+ }
257+
258+ private void ThrowIfNotInitialized ( )
259+ {
260+ if ( ! _isInitialized )
261+ throw new InvalidOperationException ( $ "Plugin '{ Metadata . Name } ' v{ Metadata . Version } is not initialized.") ;
262+ }
263+
264+ #endregion
229265}
0 commit comments