Skip to content

Commit 3d38ade

Browse files
authored
Restore old querying implementation for Execute and ExecuteBatch (#51)
1 parent 2d794fa commit 3d38ade

File tree

2 files changed

+75
-71
lines changed

2 files changed

+75
-71
lines changed

PowerSync/PowerSync.Common/MDSQLite/MDSQLiteConnection.cs

Lines changed: 74 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ public void FlushUpdates()
5656
}
5757

5858
var groupedUpdates = updateBuffer
59-
.GroupBy(update => update.Table)
60-
.ToDictionary(
61-
group => group.Key,
62-
group => group.Select(update => new TableUpdateOperation(update.OpType, update.RowId)).ToArray()
63-
);
59+
.GroupBy(update => update.Table)
60+
.ToDictionary(
61+
group => group.Key,
62+
group => group.Select(update => new TableUpdateOperation(update.OpType, update.RowId)).ToArray()
63+
);
6464

6565
var batchedUpdate = new BatchedUpdateNotification
6666
{
@@ -81,19 +81,15 @@ private static List<string> PrepareQueryString(ref string query, int parameterCo
8181
return parameterList;
8282
}
8383

84-
int placeholderCount = query.Count(c => c == '?');
85-
if (placeholderCount != parameterCount)
86-
{
87-
throw new ArgumentException($"Number of parameters ({parameterCount}) does not match the number of `?` placeholders ({placeholderCount}) in the query.");
88-
}
89-
9084
// Replace `?` sequentially with named parameters
91-
var sb = new StringBuilder();
85+
var sb = new StringBuilder(query.Length + parameterCount * 7);
9286
int lastPos = 0;
9387
int currentPos;
9488
for (int i = 0; i < parameterCount; i++)
9589
{
9690
currentPos = query.IndexOf('?', lastPos);
91+
if (currentPos == -1)
92+
throw new ArgumentException($"Not enough `?` placeholders for {parameterCount} parameters.");
9793

9894
string paramName = $"@param{i}";
9995
parameterList.Add(paramName);
@@ -115,7 +111,7 @@ private static List<string> PrepareQueryString(ref string query, int parameterCo
115111
return parameterList;
116112
}
117113

118-
private static DynamicParameters? PrepareQuery(ref string query, object?[]? parameters)
114+
private static Dictionary<string, object?>? PrepareQuery(ref string query, object?[]? parameters)
119115
{
120116
if (parameters == null || parameters.Length == 0)
121117
{
@@ -125,121 +121,128 @@ private static List<string> PrepareQueryString(ref string query, int parameterCo
125121
int parameterCount = parameters.Length;
126122
var parameterNames = PrepareQueryString(ref query, parameterCount);
127123

128-
var dynamicParams = new DynamicParameters();
124+
var paramDict = new Dictionary<string, object?>(parameterCount);
129125

130126
for (int i = 0; i < parameterCount; i++)
131127
{
132-
dynamicParams.Add(parameterNames[i], parameters[i]);
128+
paramDict[parameterNames[i]] = parameters[i];
133129
}
134130

135-
return dynamicParams;
136-
}
137-
138-
private static List<DynamicParameters>? PrepareQuery(ref string query, object?[][]? parameters)
139-
{
140-
if (parameters == null || parameters.Length == 0)
141-
{
142-
return null;
143-
}
144-
145-
var parameterCount = parameters[0].Length;
146-
if (parameterCount == 0)
147-
{
148-
return null;
149-
}
150-
151-
var parameterNames = PrepareQueryString(ref query, parameterCount);
152-
153-
var dynamicParamsList = new List<DynamicParameters>();
154-
155-
foreach (var paramSet in parameters)
156-
{
157-
if (paramSet.Length != parameterCount)
158-
{
159-
throw new ArgumentException("Parameter sets have different number of arguments.");
160-
}
161-
162-
var dynamicParams = new DynamicParameters();
163-
for (int i = 0; i < parameterCount; i++)
164-
{
165-
dynamicParams.Add(parameterNames[i], paramSet[i]);
166-
}
167-
dynamicParamsList.Add(dynamicParams);
168-
}
169-
170-
return dynamicParamsList;
131+
return paramDict;
171132
}
172133

173134
public Task<T[]> GetAll<T>(string query, object?[]? parameters = null)
174135
{
175-
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
136+
var dynamicParams = PrepareQuery(ref query, parameters);
176137
return Task.Run(async () => (await Db.QueryAsync<T>(query, dynamicParams, commandType: CommandType.Text)).ToArray());
177138
}
178139

179140
public Task<dynamic[]> GetAll(string query, object?[]? parameters = null)
180141
{
181-
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
142+
var dynamicParams = PrepareQuery(ref query, parameters);
182143
return Task.Run(async () => (await Db.QueryAsync(query, dynamicParams, commandType: CommandType.Text)).ToArray());
183144
}
184145

185146
public Task<T?> GetOptional<T>(string query, object?[]? parameters = null)
186147
{
187-
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
148+
var dynamicParams = PrepareQuery(ref query, parameters);
188149
return Task.Run(() => Db.QueryFirstOrDefaultAsync<T>(query, dynamicParams, commandType: CommandType.Text));
189150
}
190151

191152
public Task<dynamic?> GetOptional(string query, object?[]? parameters = null)
192153
{
193-
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
154+
var dynamicParams = PrepareQuery(ref query, parameters);
194155
return Task.Run(() => Db.QueryFirstOrDefaultAsync(query, dynamicParams, commandType: CommandType.Text));
195156
}
196157

197158
public Task<T> Get<T>(string query, object?[]? parameters = null)
198159
{
199-
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
160+
var dynamicParams = PrepareQuery(ref query, parameters);
200161
return Task.Run(() => Db.QueryFirstAsync<T>(query, dynamicParams, commandType: CommandType.Text));
201162
}
202163

203164
public Task<dynamic> Get(string query, object?[]? parameters = null)
204165
{
205-
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
166+
var dynamicParams = PrepareQuery(ref query, parameters);
206167
return Task.Run(() => Db.QueryFirstAsync(query, dynamicParams, commandType: CommandType.Text));
207168
}
208169

209-
public Task<NonQueryResult> Execute(string query, object?[]? parameters = null)
170+
private static void PrepareCommandParameters(SqliteCommand command, ref string query, int parameterCount)
210171
{
211-
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
212-
return Task.Run(async () =>
172+
var parameterNames = PrepareQueryString(ref query, parameterCount);
173+
command.CommandText = query;
174+
foreach (var paramName in parameterNames)
213175
{
214-
int rowsAffected = await Db.ExecuteAsync(query, dynamicParams, commandType: CommandType.Text);
215-
return new NonQueryResult
176+
var parameter = command.CreateParameter();
177+
parameter.ParameterName = paramName;
178+
command.Parameters.Add(parameter);
179+
}
180+
}
181+
182+
private static void PrepareCommand(SqliteCommand command, ref string query, object?[]? parameters)
183+
{
184+
int parameterCount = parameters?.Length ?? 0;
185+
PrepareCommandParameters(command, ref query, parameterCount);
186+
187+
if (parameters != null)
188+
{
189+
for (int i = 0; i < parameters.Length; i++)
216190
{
217-
InsertId = raw.sqlite3_last_insert_rowid(Db.Handle),
218-
RowsAffected = rowsAffected,
219-
};
220-
});
191+
command.Parameters[i].Value = parameters[i] ?? DBNull.Value;
192+
}
193+
}
221194
}
222195

196+
public Task<NonQueryResult> Execute(string query, object?[]? parameters = null) => Task.Run(() =>
197+
{
198+
using var command = Db.CreateCommand();
199+
PrepareCommand(command, ref query, parameters);
200+
201+
int rowsAffected = command.ExecuteNonQuery();
202+
return new NonQueryResult
203+
{
204+
InsertId = raw.sqlite3_last_insert_rowid(Db.Handle),
205+
RowsAffected = rowsAffected,
206+
};
207+
});
208+
223209
public Task<NonQueryResult> ExecuteBatch(string query, object?[][]? parameters = null)
224210
{
225211
if (parameters == null || parameters.Length == 0)
226212
{
227213
return Task.FromResult(new NonQueryResult { RowsAffected = 0 });
228214
}
229215

230-
List<DynamicParameters>? dynamicParamsList = PrepareQuery(ref query, parameters);
231-
if (dynamicParamsList == null)
216+
int parameterCount = parameters[0].Length;
217+
if (parameterCount == 0)
232218
{
233219
return Task.FromResult(new NonQueryResult { RowsAffected = 0 });
234220
}
235221

236-
return Task.Run(async () =>
222+
return Task.Run(() =>
237223
{
238-
int rowsAffected = await Db.ExecuteAsync(query, dynamicParamsList, commandType: CommandType.Text);
224+
int totalRowsAffected = 0;
225+
226+
using var command = Db.CreateCommand();
227+
PrepareCommandParameters(command, ref query, parameterCount);
228+
229+
foreach (var paramSet in parameters)
230+
{
231+
if (paramSet != null)
232+
{
233+
for (int i = 0; i < paramSet.Length; i++)
234+
{
235+
command.Parameters[i].Value = paramSet[i] ?? DBNull.Value;
236+
}
237+
}
238+
239+
totalRowsAffected += command.ExecuteNonQuery();
240+
}
241+
239242
return new NonQueryResult
240243
{
241244
InsertId = raw.sqlite3_last_insert_rowid(Db.Handle),
242-
RowsAffected = rowsAffected,
245+
RowsAffected = totalRowsAffected,
243246
};
244247
});
245248
}

Tests/PowerSync/PowerSync.Common.Tests/Utils/TestUtils.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Runtime.CompilerServices;
2+
23
using PowerSync.Common.Client;
34

45
namespace PowerSync.Common.Tests.Utils;

0 commit comments

Comments
 (0)