[M] Change in dart/sdk[main]: [samples/ffi] Update sqlite sample

4 views
Skip to first unread message

Daco Harkes (Gerrit)

unread,
May 5, 2022, 3:25:05 AM5/5/22
to rev...@dartlang.org

Patch set 4:Commit-Queue +1

View Change

2 comments:

  • Patchset:

    • Patch Set #4:

      Hi Michael,

      I noticed our ffi sqlite sample wasn't working anymore.

      Kind regards,

      Daco

  • File samples/ffi/sqlite/lib/src/database.dart:

    • Patch Set #1, Line 286: query.reachabilityFence();

      We can avoid this if we extend NativeResource to also stay alive till after methods in which it is a […]

      Done

To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
Gerrit-Change-Number: 143804
Gerrit-PatchSet: 4
Gerrit-Owner: Daco Harkes <dacoh...@google.com>
Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
Gerrit-Comment-Date: Thu, 05 May 2022 07:25:00 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Comment-In-Reply-To: Daco Harkes <dacoh...@google.com>
Gerrit-MessageType: comment

Daco Harkes (Gerrit)

unread,
May 5, 2022, 3:25:28 AM5/5/22
to Michael Thomsen, rev...@dartlang.org

Attention is currently required from: Michael Thomsen.

Daco Harkes would like Michael Thomsen to review this change.

View Change

[samples/ffi] Update sqlite sample

The sample wasn't working for the longest time.

Fixes:

- Null safety, and late fields.
- `dart pub` instead of `pub`.
- Use the new `NativeFinalizer` and `Finalizable` features.

Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
---
M samples/ffi/sqlite/README.md
M samples/ffi/sqlite/lib/src/bindings/bindings.dart
M samples/ffi/sqlite/lib/src/database.dart
M samples/ffi/sqlite/pubspec.yaml
4 files changed, 160 insertions(+), 49 deletions(-)

diff --git a/samples/ffi/sqlite/README.md b/samples/ffi/sqlite/README.md
index fbd5cb9..a7c65ad 100644
--- a/samples/ffi/sqlite/README.md
+++ b/samples/ffi/sqlite/README.md
@@ -23,7 +23,7 @@
Running `pub get` and `pub run example/main` should produce the following output.

```sh
-$ pub get
+$ dart pub get
Resolving dependencies... (6.8s)
+ analyzer 0.35.4
...
@@ -38,7 +38,7 @@
```

```
-$ pub run example/main
+$ dart pub run example/main
1 Chocolade chip cookie Chocolade cookie foo
2 Ginger cookie null 42
3 Cinnamon roll null null
diff --git a/samples/ffi/sqlite/lib/src/bindings/bindings.dart b/samples/ffi/sqlite/lib/src/bindings/bindings.dart
index a3d73bd..c262829 100644
--- a/samples/ffi/sqlite/lib/src/bindings/bindings.dart
+++ b/samples/ffi/sqlite/lib/src/bindings/bindings.dart
@@ -34,6 +34,10 @@
Pointer<Utf8> vfs) sqlite3_open_v2;

late int Function(Pointer<Database> database) sqlite3_close_v2;
+ late Pointer<NativeFunction<sqlite3_close_v2_native_t>>
+ sqlite3_close_v2_native;
+ late Pointer<NativeFunction<Void Function(Pointer<Database> database)>>
+ sqlite3_close_v2_native_return_void;

/// Compiling An SQL Statement
///
@@ -214,6 +218,10 @@
/// statement after it has been finalized can result in undefined and
/// undesirable behavior such as segfaults and heap corruption.
late int Function(Pointer<Statement> statement) sqlite3_finalize;
+ late Pointer<NativeFunction<sqlite3_finalize_native_t>>
+ sqlite3_finalize_native;
+ late Pointer<NativeFunction<Void Function(Pointer<Statement> statement)>>
+ sqlite3_finalize_native_return_void;

/// Number Of Columns In A Result Set
///
@@ -336,9 +344,10 @@
sqlite3_open_v2 = sqlite
.lookup<NativeFunction<sqlite3_open_v2_native_t>>("sqlite3_open_v2")
.asFunction();
- sqlite3_close_v2 = sqlite
- .lookup<NativeFunction<sqlite3_close_v2_native_t>>("sqlite3_close_v2")
- .asFunction();
+ sqlite3_close_v2_native = sqlite
+ .lookup<NativeFunction<sqlite3_close_v2_native_t>>("sqlite3_close_v2");
+ sqlite3_close_v2_native_return_void = sqlite3_close_v2_native.cast();
+ sqlite3_close_v2 = sqlite3_close_v2_native.asFunction();
sqlite3_prepare_v2 = sqlite
.lookup<NativeFunction<sqlite3_prepare_v2_native_t>>(
"sqlite3_prepare_v2")
@@ -349,9 +358,10 @@
sqlite3_reset = sqlite
.lookup<NativeFunction<sqlite3_reset_native_t>>("sqlite3_reset")
.asFunction();
- sqlite3_finalize = sqlite
- .lookup<NativeFunction<sqlite3_finalize_native_t>>("sqlite3_finalize")
- .asFunction();
+ sqlite3_finalize_native = sqlite
+ .lookup<NativeFunction<sqlite3_finalize_native_t>>("sqlite3_finalize");
+ sqlite3_finalize_native_return_void = sqlite3_finalize_native.cast();
+ sqlite3_finalize = sqlite3_finalize_native.asFunction();
sqlite3_errstr = sqlite
.lookup<NativeFunction<sqlite3_errstr_native_t>>("sqlite3_errstr")
.asFunction();
diff --git a/samples/ffi/sqlite/lib/src/database.dart b/samples/ffi/sqlite/lib/src/database.dart
index 9b0570c..fa6a8d5 100644
--- a/samples/ffi/sqlite/lib/src/database.dart
+++ b/samples/ffi/sqlite/lib/src/database.dart
@@ -21,19 +21,19 @@
///
/// This database interacts with SQLite synchonously.
class Database {
- late Pointer<types.Database> _database;
+ late DatabaseResource _database;
bool _open = false;

/// Open a database located at the file [path].
Database(String path,
[int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) {
Pointer<Pointer<types.Database>> dbOut = calloc();
- final pathC = path.toNativeUtf8();
+ final pathC = Utf8Resource(path.toNativeUtf8());
final int resultCode =
- bindings.sqlite3_open_v2(pathC, dbOut, flags, nullptr);
- _database = dbOut.value;
+ bindings.sqlite3_open_v2(pathC.unsafe(), dbOut, flags, nullptr);
+ _database = DatabaseResource(dbOut.value);
calloc.free(dbOut);
- calloc.free(pathC);
+ pathC.free();

if (resultCode == Errors.SQLITE_OK) {
_open = true;
@@ -53,7 +53,7 @@
/// avoid resource leaks.
void close() {
assert(_open);
- final int resultCode = bindings.sqlite3_close_v2(_database);
+ final int resultCode = _database.close();
if (resultCode == Errors.SQLITE_OK) {
_open = false;
} else {
@@ -63,18 +63,17 @@

/// Execute a query, discarding any returned rows.
void execute(String query) {
- Pointer<Pointer<Statement>> statementOut = calloc();
- Pointer<Utf8> queryC = query.toNativeUtf8();
- int resultCode = bindings.sqlite3_prepare_v2(
- _database, queryC, -1, statementOut, nullptr);
- Pointer<Statement> statement = statementOut.value;
+ Pointer<Pointer<Statement>> statementOut = malloc();
+ final queryC = Utf8Resource(query.toNativeUtf8());
+ int resultCode = _database.prepare(queryC, -1, statementOut, nullptr);
+ final statement = StatementResource(statementOut.value);
calloc.free(statementOut);
- calloc.free(queryC);
+ queryC.free();

while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) {
- resultCode = bindings.sqlite3_step(statement);
+ resultCode = statement.step();
}
- bindings.sqlite3_finalize(statement);
+ statement.finalize();
if (resultCode != Errors.SQLITE_DONE) {
throw _loadError(resultCode);
}
@@ -82,32 +81,33 @@

/// Evaluate a query and return the resulting rows as an iterable.
Result query(String query) {
- Pointer<Pointer<Statement>> statementOut = calloc();
- Pointer<Utf8> queryC = query.toNativeUtf8();
- int resultCode = bindings.sqlite3_prepare_v2(
- _database, queryC, -1, statementOut, nullptr);
- Pointer<Statement> statement = statementOut.value;
+ Pointer<Pointer<Statement>> statementOut = malloc();
+ final queryC = Utf8Resource(query.toNativeUtf8());
+ int resultCode = _database.prepare(queryC, -1, statementOut, nullptr);
+ final statement = StatementResource(statementOut.value);
calloc.free(statementOut);
- calloc.free(queryC);
+ queryC.free();

if (resultCode != Errors.SQLITE_OK) {
- bindings.sqlite3_finalize(statement);
+ statement.finalize();
throw _loadError(resultCode);
}

Map<String, int> columnIndices = {};
- int columnCount = bindings.sqlite3_column_count(statement);
+ int columnCount = statement.columnCount;
for (int i = 0; i < columnCount; i++) {
- String columnName =
- bindings.sqlite3_column_name(statement, i).toDartString();
+ String columnName = statement.columnName(i);
columnIndices[columnName] = i;
}

return Result._(this, statement, columnIndices);
}

- SQLiteException _loadError(int errorCode) {
- String errorMessage = bindings.sqlite3_errmsg(_database).toDartString();
+ SQLiteException _loadError([int? errorCode]) {
+ String errorMessage = _database.errmsg().toDartString();
+ if (errorCode == null) {
+ return SQLiteException(errorMessage);
+ }
String errorCodeExplanation =
bindings.sqlite3_errstr(errorCode).toDartString();
return SQLiteException(
@@ -125,7 +125,7 @@

Result._(
Database database,
- Pointer<Statement> statement,
+ StatementResource statement,
Map<String, int> columnIndices,
) : _iterator = _ResultIterator(statement, columnIndices) {}

@@ -135,7 +135,7 @@
}

class _ResultIterator implements ClosableIterator<Row> {
- final Pointer<Statement> _statement;
+ final StatementResource _statement;
final Map<String, int> _columnIndices;

Row? _currentRow;
@@ -148,7 +148,7 @@
throw SQLiteException("The result has already been closed.");
}
_currentRow?._setNotCurrent();
- int stepResult = bindings.sqlite3_step(_statement);
+ int stepResult = _statement.step();
if (stepResult == Errors.SQLITE_ROW) {
_currentRow = Row._(_statement, _columnIndices);
return true;
@@ -168,12 +168,12 @@
void close() {
_currentRow?._setNotCurrent();
_closed = true;
- bindings.sqlite3_finalize(_statement);
+ _statement.finalize();
}
}

class Row {
- final Pointer<Statement> _statement;
+ final StatementResource _statement;
final Map<String, int> _columnIndices;

bool _isCurrentRow = true;
@@ -201,12 +201,10 @@

Type dynamicType;
if (convert == Convert.DynamicType) {
- dynamicType =
- _typeFromCode(bindings.sqlite3_column_type(_statement, columnIndex));
+ dynamicType = _typeFromCode(_statement.columnType(columnIndex));
} else {
- dynamicType = _typeFromText(bindings
- .sqlite3_column_decltype(_statement, columnIndex)
- .toDartString());
+ dynamicType =
+ _typeFromText(_statement.columnDecltype(columnIndex).toDartString());
}

switch (dynamicType) {
@@ -230,7 +228,7 @@
/// integer.
int readColumnByIndexAsInt(int columnIndex) {
_checkIsCurrentRow();
- return bindings.sqlite3_column_int(_statement, columnIndex);
+ return _statement.columnInt(columnIndex);
}

/// Reads column [columnName] and converts to [Type.Text] if not text.
@@ -241,7 +239,7 @@
/// Reads column [columnIndex] and converts to [Type.Text] if not text.
String readColumnByIndexAsText(int columnIndex) {
_checkIsCurrentRow();
- return bindings.sqlite3_column_text(_statement, columnIndex).toDartString();
+ return _statement.columnText(columnIndex).toDartString();
}

void _checkIsCurrentRow() {
@@ -257,6 +255,93 @@
}
}

+class DatabaseResource implements Finalizable {
+ static final NativeFinalizer _finalizer =
+ NativeFinalizer(bindings.sqlite3_close_v2_native_return_void.cast());
+
+ /// [_statement] must never escape [StatementResource], otherwise the
+ /// [_finalizer] will run prematurely.
+ Pointer<types.Database> _database;
+
+ DatabaseResource(this._database) {
+ _finalizer.attach(this, _database.cast(), detach: this);
+ }
+
+ int close() {
+ _finalizer.detach(this);
+ return bindings.sqlite3_close_v2(_database);
+ }
+
+ int prepare(Utf8Resource query, int nbytes,
+ Pointer<Pointer<Statement>> statementOut, Pointer<Pointer<Utf8>> tail) {
+ int result = bindings.sqlite3_prepare_v2(
+ _database, query.unsafe(), nbytes, statementOut, tail);
+ return result;
+ }
+
+ Pointer<Utf8> errmsg() => bindings.sqlite3_errmsg(_database);
+}
+
+class StatementResource implements Finalizable {
+ static final NativeFinalizer _finalizer =
+ NativeFinalizer(bindings.sqlite3_finalize_native_return_void.cast());
+
+ /// [_statement] must never escape [StatementResource], otherwise the
+ /// [_finalizer] will run prematurely.
+ final Pointer<Statement> _statement;
+
+ StatementResource(this._statement) {
+ _finalizer.attach(this, _statement.cast(), detach: this);
+ }
+
+ int finalize() {
+ _finalizer.detach(this);
+ return bindings.sqlite3_finalize(_statement);
+ }
+
+ int get columnCount => bindings.sqlite3_column_count(_statement);
+
+ String columnName(int index) =>
+ bindings.sqlite3_column_name(_statement, index).toDartString();
+
+ int step() => bindings.sqlite3_step(_statement);
+
+ int columnType(int columnIndex) =>
+ bindings.sqlite3_column_type(_statement, columnIndex);
+
+ Pointer<Utf8> columnDecltype(int columnIndex) =>
+ bindings.sqlite3_column_decltype(_statement, columnIndex);
+
+ int columnInt(int columnIndex) =>
+ bindings.sqlite3_column_int(_statement, columnIndex);
+
+ Pointer<Utf8> columnText(int columnIndex) =>
+ bindings.sqlite3_column_text(_statement, columnIndex);
+}
+
+class Utf8Resource implements Finalizable {
+ static final NativeFinalizer _finalizer = NativeFinalizer(posixFree);
+
+ /// [_cString] must never escape [Utf8Resource], otherwise the
+ /// [_finalizer] will run prematurely.
+ final Pointer<Utf8> _cString;
+
+ Utf8Resource(this._cString) {
+ _finalizer.attach(this, _cString.cast(), detach: this);
+ }
+
+ void free() {
+ _finalizer.detach(this);
+ calloc.free(_cString);
+ }
+
+ /// Ensure this [Utf8Resource] stays in scope longer than the inner resource.
+ Pointer<Utf8> unsafe() => _cString;
+}
+
+final DynamicLibrary stdlib = DynamicLibrary.process();
+final posixFree = stdlib.lookup<NativeFunction<Void Function(Pointer)>>("free");
+
Type _typeFromCode(int code) {
switch (code) {
case Types.SQLITE_INTEGER:
diff --git a/samples/ffi/sqlite/pubspec.yaml b/samples/ffi/sqlite/pubspec.yaml
index 90e67f4..6ad5097 100644
--- a/samples/ffi/sqlite/pubspec.yaml
+++ b/samples/ffi/sqlite/pubspec.yaml
@@ -2,10 +2,9 @@
version: 0.0.1
description: >-
Sqlite3 wrapper. Demo for dart:ffi.
-author: Daco Harkes <dacoh...@google.com>, Samir Jindel <sji...@google.com>
environment:
- sdk: '>=2.12.0-0 <3.0.0'
+ sdk: '>=2.17.0-0 <3.0.0'
dependencies:
ffi: ^1.1.2
dev_dependencies:
- test: ^1.16.0-nullsafety.12
+ test: ^1.21.1

To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
Gerrit-Change-Number: 143804
Gerrit-PatchSet: 4
Gerrit-Owner: Daco Harkes <dacoh...@google.com>
Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
Gerrit-Reviewer: Michael Thomsen <m...@google.com>
Gerrit-CC: Commit Bot <commi...@chromium.org>
Gerrit-Attention: Michael Thomsen <m...@google.com>
Gerrit-MessageType: newchange

Daco Harkes (Gerrit)

unread,
May 5, 2022, 3:25:29 AM5/5/22
to rev...@dartlang.org, Michael Thomsen, Commit Bot

Attention is currently required from: Michael Thomsen.

View Change

1 comment:

  • Patchset:

    • Patch Set #4:

      Hi Michael,

      I noticed our ffi sqlite sample wasn't working anymore.

      Kind regards,

      Daco

To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
Gerrit-Change-Number: 143804
Gerrit-PatchSet: 4
Gerrit-Owner: Daco Harkes <dacoh...@google.com>
Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
Gerrit-Reviewer: Michael Thomsen <m...@google.com>
Gerrit-CC: Commit Bot <commi...@chromium.org>
Gerrit-Attention: Michael Thomsen <m...@google.com>
Gerrit-Comment-Date: Thu, 05 May 2022 07:25:25 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment

CBuild (Gerrit)

unread,
May 5, 2022, 4:03:25 AM5/5/22
to Daco Harkes, rev...@dartlang.org, Michael Thomsen, Commit Bot

Attention is currently required from: Daco Harkes, Michael Thomsen.

go/dart-cbuild result: SUCCESS

Details: https://goto.google.com/dart-cbuild/find/f869c62d6f8f807f809963317e2a6fe0a6cf40e6

View Change

    To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
    Gerrit-Change-Number: 143804
    Gerrit-PatchSet: 4
    Gerrit-Owner: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Michael Thomsen <m...@google.com>
    Gerrit-CC: Commit Bot <commi...@chromium.org>
    Gerrit-Attention: Daco Harkes <dacoh...@google.com>
    Gerrit-Attention: Michael Thomsen <m...@google.com>
    Gerrit-Comment-Date: Thu, 05 May 2022 08:03:22 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Michael Thomsen (Gerrit)

    unread,
    Jun 3, 2022, 5:20:05 AM6/3/22
    to Daco Harkes, rev...@dartlang.org, CBuild, Commit Bot

    Attention is currently required from: Daco Harkes.

    View Change

    1 comment:

    To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
    Gerrit-Change-Number: 143804
    Gerrit-PatchSet: 4
    Gerrit-Owner: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Michael Thomsen <m...@google.com>
    Gerrit-CC: Commit Bot <commi...@chromium.org>
    Gerrit-Attention: Daco Harkes <dacoh...@google.com>
    Gerrit-Comment-Date: Fri, 03 Jun 2022 09:20:00 +0000

    Daco Harkes (Gerrit)

    unread,
    Jun 3, 2022, 5:23:03 AM6/3/22
    to rev...@dartlang.org, CBuild, Michael Thomsen, Commit Bot

    Attention is currently required from: Michael Thomsen.

    View Change

    1 comment:

    • Patchset:

      • Yes, it's marked for review and awaiting your review.

    To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
    Gerrit-Change-Number: 143804
    Gerrit-PatchSet: 4
    Gerrit-Owner: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Michael Thomsen <m...@google.com>
    Gerrit-CC: Commit Bot <commi...@chromium.org>
    Gerrit-Attention: Michael Thomsen <m...@google.com>
    Gerrit-Comment-Date: Fri, 03 Jun 2022 09:22:59 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Michael Thomsen <m...@google.com>
    Gerrit-MessageType: comment

    Michael Thomsen (Gerrit)

    unread,
    Jun 3, 2022, 6:22:14 AM6/3/22
    to Daco Harkes, rev...@dartlang.org, CBuild, Commit Bot

    Attention is currently required from: Daco Harkes.

    View Change

    4 comments:

    • Patchset:

    • File samples/ffi/sqlite/README.md:

    • File samples/ffi/sqlite/pubspec.yaml:

      • Patch Set #4, Line 6: sdk: '>=2.17.0-0 <3.0.0'

        We can make this just `>=2.17.0 <3.0.0` as 2.17 stable is out.

    To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
    Gerrit-Change-Number: 143804
    Gerrit-PatchSet: 4
    Gerrit-Owner: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Michael Thomsen <m...@google.com>
    Gerrit-CC: Commit Bot <commi...@chromium.org>
    Gerrit-Attention: Daco Harkes <dacoh...@google.com>
    Gerrit-Comment-Date: Fri, 03 Jun 2022 10:22:09 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Daco Harkes (Gerrit)

    unread,
    Jun 6, 2022, 2:32:53 PM6/6/22
    to rev...@dartlang.org, CBuild, Michael Thomsen, Commit Bot

    Attention is currently required from: Michael Thomsen.

    Patch set 6:Commit-Queue +2

    View Change

    4 comments:

    • Patchset:

    • File samples/ffi/sqlite/README.md:

      • Patch Set #4, Line 23: Running `pub get` and `pub run example/main` should produce the following output.

        just `dart run`

      • Done

      • Done

    • File samples/ffi/sqlite/pubspec.yaml:

      • Patch Set #4, Line 6: sdk: '>=2.17.0-0 <3.0.0'

        We can make this just `>=2.17.0 <3.0.0` as 2.17 stable is out.

      • Done

    To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
    Gerrit-Change-Number: 143804
    Gerrit-PatchSet: 6
    Gerrit-Owner: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
    Gerrit-Reviewer: Michael Thomsen <m...@google.com>
    Gerrit-CC: Commit Bot <commi...@chromium.org>
    Gerrit-Attention: Michael Thomsen <m...@google.com>
    Gerrit-Comment-Date: Mon, 06 Jun 2022 18:32:48 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes

    CBuild (Gerrit)

    unread,
    Jun 6, 2022, 3:12:39 PM6/6/22
    to Daco Harkes, rev...@dartlang.org, Michael Thomsen, Commit Bot

    Attention is currently required from: Daco Harkes, Michael Thomsen.

    go/dart-cbuild result: FAILURE (NO REGRESSIONS DETECTED)

    Details: https://goto.google.com/dart-cbuild/find/95b59b06d6f8551ff547a03914c83a3c764c3985

    View Change

      To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: sdk
      Gerrit-Branch: main
      Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
      Gerrit-Change-Number: 143804
      Gerrit-PatchSet: 6
      Gerrit-Owner: Daco Harkes <dacoh...@google.com>
      Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
      Gerrit-Reviewer: Michael Thomsen <m...@google.com>
      Gerrit-CC: Commit Bot <commi...@chromium.org>
      Gerrit-Attention: Daco Harkes <dacoh...@google.com>
      Gerrit-Attention: Michael Thomsen <m...@google.com>
      Gerrit-Comment-Date: Mon, 06 Jun 2022 19:12:36 +0000

      Michael Thomsen (Gerrit)

      unread,
      Jun 7, 2022, 8:09:10 AM6/7/22
      to Daco Harkes, rev...@dartlang.org, CBuild, Commit Bot

      Attention is currently required from: Daco Harkes.

      Patch set 6:Code-Review +1

      View Change

        To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: sdk
        Gerrit-Branch: main
        Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
        Gerrit-Change-Number: 143804
        Gerrit-PatchSet: 6
        Gerrit-Owner: Daco Harkes <dacoh...@google.com>
        Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
        Gerrit-Reviewer: Michael Thomsen <m...@google.com>
        Gerrit-CC: Commit Bot <commi...@chromium.org>
        Gerrit-Attention: Daco Harkes <dacoh...@google.com>
        Gerrit-Comment-Date: Tue, 07 Jun 2022 12:09:06 +0000
        Gerrit-HasComments: No
        Gerrit-Has-Labels: Yes
        Gerrit-MessageType: comment

        Daco Harkes (Gerrit)

        unread,
        Jun 7, 2022, 8:11:24 AM6/7/22
        to rev...@dartlang.org, Michael Thomsen, CBuild, Commit Bot

        Patch set 6:Commit-Queue +2

        View Change

        1 comment:

        To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: sdk
        Gerrit-Branch: main
        Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
        Gerrit-Change-Number: 143804
        Gerrit-PatchSet: 6
        Gerrit-Owner: Daco Harkes <dacoh...@google.com>
        Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
        Gerrit-Reviewer: Michael Thomsen <m...@google.com>
        Gerrit-CC: Commit Bot <commi...@chromium.org>
        Gerrit-Comment-Date: Tue, 07 Jun 2022 12:11:20 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: Yes
        Gerrit-MessageType: comment

        Commit Bot (Gerrit)

        unread,
        Jun 7, 2022, 8:11:44 AM6/7/22
        to Daco Harkes, rev...@dartlang.org, Michael Thomsen, CBuild

        Commit Bot submitted this change.

        View Change


        Approvals: Michael Thomsen: Looks good to me, approved Daco Harkes: Commit
        [samples/ffi] Update sqlite sample

        The sample wasn't working for the longest time.

        Fixes:

        - Null safety, and late fields.
        - `dart pub` instead of `pub`.
        - Use the new `NativeFinalizer` and `Finalizable` features.

        Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
        Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143804
        Commit-Queue: Daco Harkes <dacoh...@google.com>
        Reviewed-by: Michael Thomsen <m...@google.com>

        ---
        M samples/ffi/sqlite/README.md
        M samples/ffi/sqlite/lib/src/bindings/bindings.dart
        M samples/ffi/sqlite/lib/src/database.dart
        M samples/ffi/sqlite/pubspec.yaml
        M samples_2/ffi/sqlite/README.md
        M samples_2/ffi/sqlite/lib/src/bindings/bindings.dart
        M samples_2/ffi/sqlite/lib/src/database.dart
        M samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
        M samples_2/ffi/sqlite/pubspec.yaml
        M samples_2/ffi/sqlite/test/sqlite_test.dart
        10 files changed, 315 insertions(+), 150 deletions(-)

        diff --git a/samples/ffi/sqlite/README.md b/samples/ffi/sqlite/README.md
        index fbd5cb9..c4656df 100644
        --- a/samples/ffi/sqlite/README.md
        +++ b/samples/ffi/sqlite/README.md
        @@ -20,25 +20,10 @@
        ## Building and Running this Sample

        Building and running this sample is done through pub.
        -Running `pub get` and `pub run example/main` should produce the following output.
        +Running `dart run example/main` should produce the following output.

        ```sh
        -$ pub get
        -Resolving dependencies... (6.8s)
        -+ analyzer 0.35.4
        -...
        -+ yaml 2.1.15
        -Downloading analyzer 0.35.4...
        -Downloading kernel 0.3.14...
        -Downloading front_end 0.1.14...
        -Changed 47 dependencies!
        -Precompiling executables... (18.0s)
        -Precompiled test:test.
        -
        -```
        -
        -```
        -$ pub run example/main
        +$ dart run example/main
        index 90e67f4..ab886aa 100644

        --- a/samples/ffi/sqlite/pubspec.yaml
        +++ b/samples/ffi/sqlite/pubspec.yaml
        @@ -2,10 +2,9 @@
        version: 0.0.1
        description: >-
        Sqlite3 wrapper. Demo for dart:ffi.
        -author: Daco Harkes <dacoh...@google.com>, Samir Jindel <sji...@google.com>
        environment:
        - sdk: '>=2.12.0-0 <3.0.0'
        +  sdk: '>=2.17.0 <3.0.0'
        dependencies:
        - ffi: ^1.1.2
        + ffi: ^2.0.0

        dev_dependencies:
        - test: ^1.16.0-nullsafety.12
        + test: ^1.21.1
        diff --git a/samples_2/ffi/sqlite/README.md b/samples_2/ffi/sqlite/README.md
        index fbd5cb9..c4656df 100644
        --- a/samples_2/ffi/sqlite/README.md
        +++ b/samples_2/ffi/sqlite/README.md
        @@ -20,25 +20,10 @@
        ## Building and Running this Sample

        Building and running this sample is done through pub.
        -Running `pub get` and `pub run example/main` should produce the following output.
        +Running `dart run example/main` should produce the following output.

        ```sh
        -$ pub get
        -Resolving dependencies... (6.8s)
        -+ analyzer 0.35.4
        -...
        -+ yaml 2.1.15
        -Downloading analyzer 0.35.4...
        -Downloading kernel 0.3.14...
        -Downloading front_end 0.1.14...
        -Changed 47 dependencies!
        -Precompiling executables... (18.0s)
        -Precompiled test:test.
        -
        -```
        -
        -```
        -$ pub run example/main
        +$ dart run example/main

        1 Chocolade chip cookie Chocolade cookie foo
        2 Ginger cookie null 42
        3 Cinnamon roll null null
        diff --git a/samples_2/ffi/sqlite/lib/src/bindings/bindings.dart b/samples_2/ffi/sqlite/lib/src/bindings/bindings.dart
        index a1cdba7..2491813 100644
        --- a/samples_2/ffi/sqlite/lib/src/bindings/bindings.dart
        +++ b/samples_2/ffi/sqlite/lib/src/bindings/bindings.dart
        @@ -33,6 +33,9 @@
        int flags, Pointer<Utf8> vfs) sqlite3_open_v2;


        int Function(Pointer<Database> database) sqlite3_close_v2;
        +  Pointer<NativeFunction<sqlite3_close_v2_native_t>> sqlite3_close_v2_native;
        + Pointer<NativeFunction<Void Function(Pointer<Database> database)>>

        + sqlite3_close_v2_native_return_void;

        /// Compiling An SQL Statement
        ///
        @@ -213,6 +216,9 @@

        /// statement after it has been finalized can result in undefined and
        /// undesirable behavior such as segfaults and heap corruption.
           int Function(Pointer<Statement> statement) sqlite3_finalize;
        +  Pointer<NativeFunction<sqlite3_finalize_native_t>> sqlite3_finalize_native;
        + Pointer<NativeFunction<Void Function(Pointer<Statement> statement)>>

        + sqlite3_finalize_native_return_void;

        /// Number Of Columns In A Result Set
        ///
        @@ -335,9 +341,10 @@

        sqlite3_open_v2 = sqlite
        .lookup<NativeFunction<sqlite3_open_v2_native_t>>("sqlite3_open_v2")
        .asFunction();
        - sqlite3_close_v2 = sqlite
        - .lookup<NativeFunction<sqlite3_close_v2_native_t>>("sqlite3_close_v2")
        - .asFunction();
        + sqlite3_close_v2_native = sqlite
        + .lookup<NativeFunction<sqlite3_close_v2_native_t>>("sqlite3_close_v2");
        + sqlite3_close_v2_native_return_void = sqlite3_close_v2_native.cast();
        + sqlite3_close_v2 = sqlite3_close_v2_native.asFunction();
        sqlite3_prepare_v2 = sqlite
        .lookup<NativeFunction<sqlite3_prepare_v2_native_t>>(
        "sqlite3_prepare_v2")
        @@ -348,9 +355,10 @@

        sqlite3_reset = sqlite
        .lookup<NativeFunction<sqlite3_reset_native_t>>("sqlite3_reset")
        .asFunction();
        - sqlite3_finalize = sqlite
        - .lookup<NativeFunction<sqlite3_finalize_native_t>>("sqlite3_finalize")
        - .asFunction();
        + sqlite3_finalize_native = sqlite
        + .lookup<NativeFunction<sqlite3_finalize_native_t>>("sqlite3_finalize");
        + sqlite3_finalize_native_return_void = sqlite3_finalize_native.cast();
        + sqlite3_finalize = sqlite3_finalize_native.asFunction();
        sqlite3_errstr = sqlite
        .lookup<NativeFunction<sqlite3_errstr_native_t>>("sqlite3_errstr")
        .asFunction();
        diff --git a/samples_2/ffi/sqlite/lib/src/database.dart b/samples_2/ffi/sqlite/lib/src/database.dart
        index d65724f..5bfc770 100644
        --- a/samples_2/ffi/sqlite/lib/src/database.dart
        +++ b/samples_2/ffi/sqlite/lib/src/database.dart
        @@ -23,19 +23,19 @@

        ///
        /// This database interacts with SQLite synchonously.
        class Database {
        -  Pointer<types.Database> _database;
        + DatabaseResource _database;

        bool _open = false;

        /// Open a database located at the file [path].
        Database(String path,
        [int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) {
        Pointer<Pointer<types.Database>> dbOut = calloc();
        - final pathC = path.toNativeUtf8();
        + final pathC = Utf8Resource(path.toNativeUtf8());
        final int resultCode =
        - bindings.sqlite3_open_v2(pathC, dbOut, flags, nullptr);
        - _database = dbOut.value;
        + bindings.sqlite3_open_v2(pathC.unsafe(), dbOut, flags, nullptr);
        + _database = DatabaseResource(dbOut.value);
        calloc.free(dbOut);
        - calloc.free(pathC);
        + pathC.free();

        if (resultCode == Errors.SQLITE_OK) {
        _open = true;
        @@ -55,7 +55,7 @@

        /// avoid resource leaks.
        void close() {
        assert(_open);
        - final int resultCode = bindings.sqlite3_close_v2(_database);
        + final int resultCode = _database.close();
        if (resultCode == Errors.SQLITE_OK) {
        _open = false;
        } else {
        @@ -65,18 +65,17 @@


        /// Execute a query, discarding any returned rows.
        void execute(String query) {
        - Pointer<Pointer<Statement>> statementOut = calloc();
        - Pointer<Utf8> queryC = query.toNativeUtf8();
        - int resultCode = bindings.sqlite3_prepare_v2(
        - _database, queryC, -1, statementOut, nullptr);
        - Pointer<Statement> statement = statementOut.value;
        + Pointer<Pointer<Statement>> statementOut = malloc();
        + final queryC = Utf8Resource(query.toNativeUtf8());
        + int resultCode = _database.prepare(queryC, -1, statementOut, nullptr);
        + final statement = StatementResource(statementOut.value);
        calloc.free(statementOut);
        - calloc.free(queryC);
        + queryC.free();

        while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) {
        - resultCode = bindings.sqlite3_step(statement);
        + resultCode = statement.step();
        }
        - bindings.sqlite3_finalize(statement);
        + statement.finalize();
        if (resultCode != Errors.SQLITE_DONE) {
        throw _loadError(resultCode);
        }
        @@ -84,24 +83,22 @@
        @@ -109,7 +106,7 @@
        }

        SQLiteException _loadError([int errorCode]) {

        - String errorMessage = bindings.sqlite3_errmsg(_database).toDartString();
        +    String errorMessage = _database.errmsg().toDartString();
        if (errorCode == null) {
        return SQLiteException(errorMessage);
        }
        @@ -126,18 +123,13 @@
        /// Please note that this iterator should be [close]d manually if not all [Row]s
        /// are consumed.
        class Result extends IterableBase<Row> implements ClosableIterable<Row> {
        - final Database _database;
        final ClosableIterator<Row> _iterator;

        - final Pointer<Statement> _statement;
        -  final Map<String, int> _columnIndices;
        -
        - Row _currentRow = null;

        Result._(
        - this._database,
        - this._statement,
        - this._columnIndices,
        - ) : _iterator = _ResultIterator(_statement, _columnIndices) {}
        + Database database,
        + StatementResource statement,
        + Map<String, int> columnIndices,
        + ) : _iterator = _ResultIterator(statement, columnIndices) {}

        void close() => _iterator.close();

        @@ -145,10 +137,10 @@

        }

        class _ResultIterator implements ClosableIterator<Row> {
        - final Pointer<Statement> _statement;
        + final StatementResource _statement;
        final Map<String, int> _columnIndices;

        -  Row _currentRow = null;
        + Row _currentRow;
        bool _closed = false;

        _ResultIterator(this._statement, this._columnIndices) {}
        @@ -157,8 +149,10 @@
        if (_closed) {

        throw SQLiteException("The result has already been closed.");
        }
        -    _currentRow?._setNotCurrent();

        - int stepResult = bindings.sqlite3_step(_statement);
        +    if (_currentRow != null) {
        + _currentRow._setNotCurrent();
        + }

        + int stepResult = _statement.step();
        if (stepResult == Errors.SQLITE_ROW) {
        _currentRow = Row._(_statement, _columnIndices);
        return true;
        @@ -176,14 +170,14 @@
        }

        void close() {
        - _currentRow?._setNotCurrent();
        + _currentRow._setNotCurrent();

        _closed = true;
        - bindings.sqlite3_finalize(_statement);
        + _statement.finalize();
        }
        }

        class Row {
        - final Pointer<Statement> _statement;
        + final StatementResource _statement;
        final Map<String, int> _columnIndices;

        bool _isCurrentRow = true;
        @@ -211,12 +205,10 @@


        Type dynamicType;
        if (convert == Convert.DynamicType) {
        - dynamicType =
        - _typeFromCode(bindings.sqlite3_column_type(_statement, columnIndex));
        + dynamicType = _typeFromCode(_statement.columnType(columnIndex));
        } else {
        - dynamicType = _typeFromText(bindings
        - .sqlite3_column_decltype(_statement, columnIndex)
        - .toDartString());
        + dynamicType =
        + _typeFromText(_statement.columnDecltype(columnIndex).toDartString());
        }

        switch (dynamicType) {
        @@ -226,7 +218,6 @@
        return readColumnByIndexAsText(columnIndex);
        case Type.Null:
        return null;
        - break;
        default:
        }
        }
        @@ -241,7 +232,7 @@

        /// integer.
        int readColumnByIndexAsInt(int columnIndex) {
        _checkIsCurrentRow();
        - return bindings.sqlite3_column_int(_statement, columnIndex);
        + return _statement.columnInt(columnIndex);
        }

        /// Reads column [columnName] and converts to [Type.Text] if not text.
        @@ -252,7 +243,7 @@

        /// Reads column [columnIndex] and converts to [Type.Text] if not text.
        String readColumnByIndexAsText(int columnIndex) {
        _checkIsCurrentRow();
        - return bindings.sqlite3_column_text(_statement, columnIndex).toDartString();
        + return _statement.columnText(columnIndex).toDartString();
        }

        void _checkIsCurrentRow() {
        @@ -268,6 +259,93 @@
        @@ -297,7 +375,6 @@
        case "null":
        return Type.Null;
        }
        - if (textRepresentation == null) return Type.Null;
        throw Exception("Unknown type [$textRepresentation]");
        }

        diff --git a/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart b/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
        index b783ad8..fccdca3 100644
        --- a/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
        +++ b/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
        @@ -7,8 +7,7 @@
        import 'dart:ffi';
        import 'dart:io' show Platform;

        -String _platformPath(String name, {String path}) {
        - if (path == null) path = "";
        +String _platformPath(String name, String path) {
        if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
        return path + "lib" + name + ".so";
        if (Platform.isMacOS) return path + "lib" + name + ".dylib";
        @@ -16,7 +15,7 @@
        throw Exception("Platform not implemented");
        }

        -DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
        - String fullPath = _platformPath(name, path: path);
        +DynamicLibrary dlopenPlatformSpecific(String name, {String path = ""}) {
        + String fullPath = _platformPath(name, path);
        return DynamicLibrary.open(fullPath);
        }
        diff --git a/samples_2/ffi/sqlite/pubspec.yaml b/samples_2/ffi/sqlite/pubspec.yaml
        index 762107f..ab886aa 100644
        --- a/samples_2/ffi/sqlite/pubspec.yaml
        +++ b/samples_2/ffi/sqlite/pubspec.yaml

        @@ -2,10 +2,9 @@
        version: 0.0.1
        description: >-
        Sqlite3 wrapper. Demo for dart:ffi.
        -author: Daco Harkes <dacoh...@google.com>, Samir Jindel <sji...@google.com>
        environment:
        -  sdk: '>=2.1.0 <3.0.0'
        + sdk: '>=2.17.0 <3.0.0'
        dependencies:
        - ffi: ^1.1.2
        + ffi: ^2.0.0
        dev_dependencies:
        - test: ^1.5.3
        + test: ^1.21.1
        diff --git a/samples_2/ffi/sqlite/test/sqlite_test.dart b/samples_2/ffi/sqlite/test/sqlite_test.dart
        index 91efe13..8640438 100644
        --- a/samples_2/ffi/sqlite/test/sqlite_test.dart
        +++ b/samples_2/ffi/sqlite/test/sqlite_test.dart
        @@ -49,8 +49,7 @@
        expect(true, 1 <= id && id <= 3);
        String name = r.readColumnByIndex(1);
        expect(true, name is String);
        - String alternativeName = r.readColumn("alternative_name");
        - expect(true, alternativeName is String || alternativeName == null);
        + final alternativeName = r.readColumn("alternative_name") as String;
        dynamic multiTypedValue = r.readColumn("multi_typed_column");
        expect(
        true,
        @@ -76,8 +75,7 @@
        expect(true, 1 <= id && id <= 3);
        String name = r.readColumnByIndex(1);
        expect(true, name is String);
        - String alternativeName = r.readColumn("alternative_name");
        - expect(true, alternativeName is String || alternativeName == null);
        + final alternativeName = r.readColumn("alternative_name") as String;
        dynamic multiTypedValue = r.readColumn("multi_typed_column");
        expect(
        true,

        To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: sdk
        Gerrit-Branch: main
        Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
        Gerrit-Change-Number: 143804
        Gerrit-PatchSet: 7
        Gerrit-Owner: Daco Harkes <dacoh...@google.com>
        Gerrit-Reviewer: Commit Bot <commi...@chromium.org>
        Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
        Gerrit-Reviewer: Michael Thomsen <m...@google.com>
        Gerrit-MessageType: merged

        CBuild (Gerrit)

        unread,
        Jun 7, 2022, 8:47:16 AM6/7/22
        to Commit Bot, Daco Harkes, rev...@dartlang.org, Michael Thomsen

        go/dart-cbuild result: FAILURE (NO REGRESSIONS DETECTED)

        Details: https://goto.google.com/dart-cbuild/find/81584f5d031fc12049f954b8510de7c36f1e56ea

        View Change

          To view, visit change 143804. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: sdk
          Gerrit-Branch: main
          Gerrit-Change-Id: I0a397abae511ab3f6762d1b2c4047226d15e36d6
          Gerrit-Change-Number: 143804
          Gerrit-PatchSet: 7
          Gerrit-Owner: Daco Harkes <dacoh...@google.com>
          Gerrit-Reviewer: Commit Bot <commi...@chromium.org>
          Gerrit-Reviewer: Daco Harkes <dacoh...@google.com>
          Gerrit-Reviewer: Michael Thomsen <m...@google.com>
          Gerrit-Comment-Date: Tue, 07 Jun 2022 12:47:12 +0000
          Reply all
          Reply to author
          Forward
          0 new messages