Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions PowerSync/PowerSync.Common/Client/PowerSyncDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ public interface IPowerSyncDatabase : IEventStream<PowerSyncDBEvent>

public Task<CrudTransaction?> GetNextCrudTransaction();

Task<NonQueryResult> Execute(string query, object[]? parameters = null);
Task<NonQueryResult> Execute(string query, object?[]? parameters = null);

Task<T[]> GetAll<T>(string sql, object[]? parameters = null);
Task<T[]> GetAll<T>(string sql, object?[]? parameters = null);

Task<T?> GetOptional<T>(string sql, object[]? parameters = null);
Task<T?> GetOptional<T>(string sql, object?[]? parameters = null);

Task<T> Get<T>(string sql, object[]? parameters = null);
Task<T> Get<T>(string sql, object?[]? parameters = null);

Task<T> ReadLock<T>(Func<ILockContext, Task<T>> fn, DBLockOptions? options = null);

Expand Down Expand Up @@ -549,24 +549,24 @@ public async Task<string> GetClientId()
return await BucketStorageAdapter.GetClientId();
}

public async Task<NonQueryResult> Execute(string query, object[]? parameters = null)
public async Task<NonQueryResult> Execute(string query, object?[]? parameters = null)
{
await WaitForReady();
return await Database.Execute(query, parameters);
}

public async Task<T[]> GetAll<T>(string query, object[]? parameters = null)
public async Task<T[]> GetAll<T>(string query, object?[]? parameters = null)
{
await WaitForReady();
return await Database.GetAll<T>(query, parameters);
}

public async Task<T?> GetOptional<T>(string query, object[]? parameters = null)
public async Task<T?> GetOptional<T>(string query, object?[]? parameters = null)
{
await WaitForReady();
return await Database.GetOptional<T>(query, parameters);
}
public async Task<T> Get<T>(string query, object[]? parameters = null)
public async Task<T> Get<T>(string query, object?[]? parameters = null)
{
await WaitForReady();
return await Database.Get<T>(query, parameters);
Expand Down Expand Up @@ -614,7 +614,7 @@ public async Task<T> WriteTransaction<T>(Func<ITransaction, Task<T>> fn, DBLockO
/// Use <see cref="SQLWatchOptions.ThrottleMs"/> to specify the minimum interval between queries.
/// Source tables are automatically detected using <c>EXPLAIN QUERY PLAN</c>.
/// </summary>
public Task Watch<T>(string query, object[]? parameters, WatchHandler<T> handler, SQLWatchOptions? options = null)
public Task Watch<T>(string query, object?[]? parameters, WatchHandler<T> handler, SQLWatchOptions? options = null)
{
var tcs = new TaskCompletionSource<bool>();
Task.Run(async () =>
Expand Down Expand Up @@ -658,7 +658,7 @@ public Task Watch<T>(string query, object[]? parameters, WatchHandler<T> handler

private record ExplainedResult(string opcode, int p2, int p3);
private record TableSelectResult(string tbl_name);
public async Task<string[]> ResolveTables(string sql, object[]? parameters = null, SQLWatchOptions? options = null)
public async Task<string[]> ResolveTables(string sql, object?[]? parameters = null, SQLWatchOptions? options = null)
{
List<string> resolvedTables = options?.Tables != null ? [.. options.Tables] : [];

Expand Down
10 changes: 5 additions & 5 deletions PowerSync/PowerSync.Common/DB/IDBAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ public class QueryRows
public interface IDBGetUtils
{
// Execute a read-only query and return results.
Task<T[]> GetAll<T>(string sql, object[]? parameters = null);
Task<T[]> GetAll<T>(string sql, object?[]? parameters = null);

// Execute a read-only query and return the first result, or null if the ResultSet is empty.
Task<T?> GetOptional<T>(string sql, object[]? parameters = null);
Task<T?> GetOptional<T>(string sql, object?[]? parameters = null);

// Execute a read-only query and return the first result, error if the ResultSet is empty.
Task<T> Get<T>(string sql, object[]? parameters = null);
Task<T> Get<T>(string sql, object?[]? parameters = null);
}

public interface ILockContext : IDBGetUtils
{
// Execute a single write statement.
Task<NonQueryResult> Execute(string query, object[]? parameters = null);
Task<NonQueryResult> Execute(string query, object?[]? parameters = null);
}

public interface ITransaction : ILockContext
Expand Down Expand Up @@ -117,7 +117,7 @@ public interface IDBAdapter : IEventStream<DBAdapterEvent>, ILockContext
/// <summary>
/// Execute a batch of write statements.
/// </summary>
Task<QueryResult> ExecuteBatch(string query, object[][]? parameters = null);
Task<QueryResult> ExecuteBatch(string query, object?[][]? parameters = null);

/// <summary>
/// The name of the adapter.
Expand Down
18 changes: 9 additions & 9 deletions PowerSync/PowerSync.Common/MDSQLite/MDSQLiteAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,29 +144,29 @@ protected virtual void LoadExtension(SqliteConnection db)
readConnection?.Close();
}

public async Task<NonQueryResult> Execute(string query, object[]? parameters = null)
public async Task<NonQueryResult> Execute(string query, object?[]? parameters = null)
{
return await WriteLock((ctx) => ctx.Execute(query, parameters));
}

public Task<QueryResult> ExecuteBatch(string query, object[][]? parameters = null)
public Task<QueryResult> ExecuteBatch(string query, object?[][]? parameters = null)
{
// https://learn.microsoft.com/en-gb/dotnet/standard/data/sqlite/batching
throw new NotImplementedException();
}

public async Task<T> Get<T>(string sql, object[]? parameters = null)
public async Task<T> Get<T>(string sql, object?[]? parameters = null)
{
return await ReadLock((ctx) => ctx.Get<T>(sql, parameters));
;
}

public async Task<T[]> GetAll<T>(string sql, object[]? parameters = null)
public async Task<T[]> GetAll<T>(string sql, object?[]? parameters = null)
{
return await ReadLock((ctx) => ctx.GetAll<T>(sql, parameters));
}

public async Task<T?> GetOptional<T>(string sql, object[]? parameters = null)
public async Task<T?> GetOptional<T>(string sql, object?[]? parameters = null)
{
return await ReadLock((ctx) => ctx.GetOptional<T>(sql, parameters));
}
Expand Down Expand Up @@ -302,22 +302,22 @@ public async Task Rollback()
await connection.Execute("ROLLBACK");
}

public Task<NonQueryResult> Execute(string query, object[]? parameters = null)
public Task<NonQueryResult> Execute(string query, object?[]? parameters = null)
{
return connection.Execute(query, parameters);
}

public Task<T> Get<T>(string sql, object[]? parameters = null)
public Task<T> Get<T>(string sql, object?[]? parameters = null)
{
return connection.Get<T>(sql, parameters);
}

public Task<T[]> GetAll<T>(string sql, object[]? parameters = null)
public Task<T[]> GetAll<T>(string sql, object?[]? parameters = null)
{
return connection.GetAll<T>(sql, parameters);
}

public Task<T?> GetOptional<T>(string sql, object[]? parameters = null)
public Task<T?> GetOptional<T>(string sql, object?[]? parameters = null)
{
return connection.GetOptional<T>(sql, parameters);
}
Expand Down
12 changes: 6 additions & 6 deletions PowerSync/PowerSync.Common/MDSQLite/MDSQLiteConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public void FlushUpdates()
Emit(new DBAdapterEvent { TablesUpdated = batchedUpdate });
}

private static void PrepareCommand(SqliteCommand command, string query, object[]? parameters)
private static void PrepareCommand(SqliteCommand command, string query, object?[]? parameters)
{
if (parameters == null || parameters.Length == 0)
{
Expand Down Expand Up @@ -113,7 +113,7 @@ private static void PrepareCommand(SqliteCommand command, string query, object[]
}
}

public async Task<NonQueryResult> Execute(string query, object[]? parameters = null)
public async Task<NonQueryResult> Execute(string query, object?[]? parameters = null)
{
using var command = Db.CreateCommand();
PrepareCommand(command, query, parameters);
Expand All @@ -127,7 +127,7 @@ public async Task<NonQueryResult> Execute(string query, object[]? parameters = n
};
}

public async Task<QueryResult> ExecuteQuery(string query, object[]? parameters = null)
public async Task<QueryResult> ExecuteQuery(string query, object?[]? parameters = null)
{
var result = new QueryResult();
using var command = Db.CreateCommand();
Expand All @@ -151,7 +151,7 @@ public async Task<QueryResult> ExecuteQuery(string query, object[]? parameters =
return result;
}

public async Task<T[]> GetAll<T>(string sql, object[]? parameters = null)
public async Task<T[]> GetAll<T>(string sql, object?[]? parameters = null)
{
var result = await ExecuteQuery(sql, parameters);

Expand All @@ -177,7 +177,7 @@ public async Task<T[]> GetAll<T>(string sql, object[]? parameters = null)
return [.. items];
}

public async Task<T?> GetOptional<T>(string sql, object[]? parameters = null)
public async Task<T?> GetOptional<T>(string sql, object?[]? parameters = null)
{
var result = await ExecuteQuery(sql, parameters);

Expand All @@ -198,7 +198,7 @@ public async Task<T[]> GetAll<T>(string sql, object[]? parameters = null)
return JsonConvert.DeserializeObject<T>(json);
}

public async Task<T> Get<T>(string sql, object[]? parameters = null)
public async Task<T> Get<T>(string sql, object?[]? parameters = null)
{
return await GetOptional<T>(sql, parameters) ?? throw new InvalidOperationException("Result set is empty");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,25 @@ await db.Execute(
Assert.Equal(age.ToString(), row.make);
}

[Fact]
public async Task QueryWithNullParams()
{
var id = Guid.NewGuid().ToString();
var name = "Test user";

await db.Execute(
"INSERT INTO assets(id, description, make) VALUES(?, ?, ?)",
[id, name, null]
);

var result = await db.GetAll<AssetResult>("SELECT id, description, make FROM assets WHERE id = ? AND make IS NULL", [id]);

Assert.Single(result);
var row = result.First();
Assert.Equal(name, row.description);
Assert.Equal(null, row.make);
}

[Fact]
public async Task FailedInsertTest()
{
Expand Down
1 change: 0 additions & 1 deletion demos/CommandLine/Demo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ static async Task Main()

await db.Connect(connector, new PowerSync.Common.Client.Sync.Stream.PowerSyncConnectionOptions
{
ClientImplementation = PowerSync.Common.Client.Sync.Stream.SyncClientImplementation.RUST,
AppMetadata = new Dictionary<string, string>
{
{ "app_version", GetAppVersion() },
Expand Down