Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion sqlite3/lib/src/api/functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:meta/meta.dart';
/// A scalar function exposed to sql.
///
/// {@template sqlite3_function_behavior}
/// The function must either return a `bool`, `num`, `String`, `List<int>` or
/// The function must either return a `bool`, `num`, `String`, `Uint8List` or
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should force users to return a Uint8List here. It's a breaking change which IMO is not necessary. Most users return a Uint8List already, I don't see much value in an enforcement in the type system.

We can check if we got an Uint8List and implicitly copy to an Uint8List if we didn't.

/// `null`.
///
/// If invoking the function throws a Dart exception, the sql function will
Expand Down
10 changes: 6 additions & 4 deletions sqlite3/lib/src/ffi/ffi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ extension ValueUtils on Pointer<sqlite3_value> {
}
}

final utf8Encode = utf8.encoder.convert;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should only define this once, the usage in memory.dart can just import this one.


extension ContextUtils on Pointer<sqlite3_context> {
Pointer<Void> aggregateContext(Bindings bindings, int bytes) {
return bindings.sqlite3_aggregate_context(this, bytes);
Expand All @@ -88,13 +90,13 @@ extension ContextUtils on Pointer<sqlite3_context> {
} else if (result is bool) {
bindings.sqlite3_result_int64(this, result ? 1 : 0);
} else if (result is String) {
final bytes = utf8.encode(result);
Uint8List bytes = utf8Encode(result);
final ptr = allocateBytes(bytes);

bindings.sqlite3_result_text(
this, ptr.cast(), bytes.length, SQLITE_TRANSIENT);
ptr.free();
} else if (result is List<int>) {
} else if (result is Uint8List) {
final ptr = allocateBytes(result);

bindings.sqlite3_result_blob64(
Expand All @@ -104,7 +106,7 @@ extension ContextUtils on Pointer<sqlite3_context> {
}

void setError(Bindings bindings, String description) {
final bytes = utf8.encode(description);
final Uint8List bytes = utf8Encode(description);
final ptr = allocateBytes(bytes);

bindings.sqlite3_result_error(this, ptr.cast(), bytes.length);
Expand Down Expand Up @@ -148,7 +150,7 @@ class ValueList extends ListBase<Object?> {
}

final result = argArray[index].read(bindings);
if (result is String || result is List<int>) {
if (result is String || result is Uint8List) {
// Cache to avoid excessive copying in case the argument is loaded
// multiple times
_cachedCopies[index] = result;
Expand Down
5 changes: 3 additions & 2 deletions sqlite3/lib/src/ffi/memory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extension FreePointerExtension on Pointer {
void free() => allocate.free(this);
}

Pointer<Uint8> allocateBytes(List<int> bytes, {int additionalLength = 0}) {
Pointer<Uint8> allocateBytes(Uint8List bytes, {int additionalLength = 0}) {
final ptr = allocate.allocate<Uint8>(bytes.length + additionalLength);

final data = Uint8List(bytes.length + additionalLength)..setAll(0, bytes);
Expand All @@ -40,6 +40,7 @@ Pointer<Uint8> allocateBytes(List<int> bytes, {int additionalLength = 0}) {
return ptr;
}

final utf8Encode = utf8.encoder.convert;
Pointer<char> allocateZeroTerminated(String string) {
return allocateBytes(utf8.encode(string), additionalLength: 1).cast();
return allocateBytes(utf8Encode(string), additionalLength: 1).cast();
}
4 changes: 2 additions & 2 deletions sqlite3/lib/src/impl/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class DatabaseImpl implements Database {
final pzTail =
checkNoTail ? allocate<Pointer<char>>() : nullPtr<Pointer<char>>();

final bytes = utf8.encode(sql);
final bytes = utf8Encode(sql);
final sqlPtr = allocateBytes(bytes);

var prepFlags = 0;
Expand Down Expand Up @@ -229,7 +229,7 @@ class DatabaseImpl implements Database {
}

Pointer<Uint8> _functionName(String functionName) {
final functionNameBytes = utf8.encode(functionName);
final functionNameBytes = utf8Encode(functionName);

if (functionNameBytes.length > 255) {
throw ArgumentError.value(functionName, 'functionName',
Expand Down
6 changes: 3 additions & 3 deletions sqlite3/lib/src/impl/statement.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ class PreparedStatementImpl implements PreparedStatement {
} else if (param is double) {
_bindings.sqlite3_bind_double(_stmt, i, param.toDouble());
} else if (param is String) {
final bytes = utf8.encode(param);
final bytes = utf8Encode(param);
final ptr = allocateBytes(bytes);
_allocatedWhileBinding.add(ptr);

_bindings.sqlite3_bind_text(
_stmt, i, ptr.cast(), bytes.length, nullPtr());
} else if (param is List<int>) {
} else if (param is Uint8List) {
if (param.isEmpty) {
// malloc(0) is implementation-defined and might return a null
// pointer, which is not what we want: Passing a null-pointer to
Expand All @@ -134,7 +134,7 @@ class PreparedStatementImpl implements PreparedStatement {
param,
'params[$i]',
'Allowed parameters must either be null or an int, num, String or '
'List<int>.',
'Uint8List.',
);
}
}
Expand Down