diff --git a/example/lib/database.dart b/example/lib/database.dart index 037973f8..f856eb3b 100644 --- a/example/lib/database.dart +++ b/example/lib/database.dart @@ -4,7 +4,7 @@ import 'package:example/task.dart'; import 'package:example/task_dao.dart'; import 'package:example/type_converter.dart'; import 'package:floor/floor.dart'; -import 'package:sqflite/sqflite.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqflite.dart' as sqflite; part 'database.g.dart'; @@ -13,3 +13,12 @@ part 'database.g.dart'; abstract class FlutterDatabase extends FloorDatabase { TaskDao get taskDao; } + + +void tete() async { + sqflite.Database db = await sqflite.openDatabase( + "path", + password: "my password", + // onCreate, onUpgrade... + ); +} \ No newline at end of file diff --git a/example/lib/database.g.dart b/example/lib/database.g.dart deleted file mode 100644 index 39dcf3a9..00000000 --- a/example/lib/database.g.dart +++ /dev/null @@ -1,283 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'database.dart'; - -// ************************************************************************** -// FloorGenerator -// ************************************************************************** - -abstract class $FlutterDatabaseBuilderContract { - /// Adds migrations to the builder. - $FlutterDatabaseBuilderContract addMigrations(List migrations); - - /// Adds a database [Callback] to the builder. - $FlutterDatabaseBuilderContract addCallback(Callback callback); - - /// Creates the database and initializes it. - Future build(); -} - -// ignore: avoid_classes_with_only_static_members -class $FloorFlutterDatabase { - /// Creates a database builder for a persistent database. - /// Once a database is built, you should keep a reference to it and re-use it. - static $FlutterDatabaseBuilderContract databaseBuilder(String name) => - _$FlutterDatabaseBuilder(name); - - /// Creates a database builder for an in memory database. - /// Information stored in an in memory database disappears when the process is killed. - /// Once a database is built, you should keep a reference to it and re-use it. - static $FlutterDatabaseBuilderContract inMemoryDatabaseBuilder() => - _$FlutterDatabaseBuilder(null); -} - -class _$FlutterDatabaseBuilder implements $FlutterDatabaseBuilderContract { - _$FlutterDatabaseBuilder(this.name); - - final String? name; - - final List _migrations = []; - - Callback? _callback; - - @override - $FlutterDatabaseBuilderContract addMigrations(List migrations) { - _migrations.addAll(migrations); - return this; - } - - @override - $FlutterDatabaseBuilderContract addCallback(Callback callback) { - _callback = callback; - return this; - } - - @override - Future build() async { - final path = name != null - ? await sqfliteDatabaseFactory.getDatabasePath(name!) - : ':memory:'; - final database = _$FlutterDatabase(); - database.database = await database.open( - path, - _migrations, - _callback, - ); - return database; - } -} - -class _$FlutterDatabase extends FlutterDatabase { - _$FlutterDatabase([StreamController? listener]) { - changeListener = listener ?? StreamController.broadcast(); - } - - TaskDao? _taskDaoInstance; - - Future open( - String path, - List migrations, [ - Callback? callback, - ]) async { - final databaseOptions = sqflite.OpenDatabaseOptions( - version: 1, - onConfigure: (database) async { - await database.execute('PRAGMA foreign_keys = ON'); - await callback?.onConfigure?.call(database); - }, - onOpen: (database) async { - await callback?.onOpen?.call(database); - }, - onUpgrade: (database, startVersion, endVersion) async { - await MigrationAdapter.runMigrations( - database, startVersion, endVersion, migrations); - - await callback?.onUpgrade?.call(database, startVersion, endVersion); - }, - onCreate: (database, version) async { - await database.execute( - 'CREATE TABLE IF NOT EXISTS `Task` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT NOT NULL, `isRead` INTEGER, `timestamp` INTEGER NOT NULL, `status` INTEGER, `type` TEXT)'); - - await callback?.onCreate?.call(database, version); - }, - ); - return sqfliteDatabaseFactory.openDatabase(path, options: databaseOptions); - } - - @override - TaskDao get taskDao { - return _taskDaoInstance ??= _$TaskDao(database, changeListener); - } -} - -class _$TaskDao extends TaskDao { - _$TaskDao( - this.database, - this.changeListener, - ) : _queryAdapter = QueryAdapter(database, changeListener), - _taskInsertionAdapter = InsertionAdapter( - database, - 'Task', - (Task item) => { - 'id': item.id, - 'message': item.message, - 'isRead': item.isRead == null ? null : (item.isRead! ? 1 : 0), - 'timestamp': _dateTimeConverter.encode(item.timestamp), - 'status': item.status?.index, - 'type': _taskTypeConverter.encode(item.type) - }, - changeListener), - _taskUpdateAdapter = UpdateAdapter( - database, - 'Task', - ['id'], - (Task item) => { - 'id': item.id, - 'message': item.message, - 'isRead': item.isRead == null ? null : (item.isRead! ? 1 : 0), - 'timestamp': _dateTimeConverter.encode(item.timestamp), - 'status': item.status?.index, - 'type': _taskTypeConverter.encode(item.type) - }, - changeListener), - _taskDeletionAdapter = DeletionAdapter( - database, - 'Task', - ['id'], - (Task item) => { - 'id': item.id, - 'message': item.message, - 'isRead': item.isRead == null ? null : (item.isRead! ? 1 : 0), - 'timestamp': _dateTimeConverter.encode(item.timestamp), - 'status': item.status?.index, - 'type': _taskTypeConverter.encode(item.type) - }, - changeListener); - - final sqflite.DatabaseExecutor database; - - final StreamController changeListener; - - final QueryAdapter _queryAdapter; - - final InsertionAdapter _taskInsertionAdapter; - - final UpdateAdapter _taskUpdateAdapter; - - final DeletionAdapter _taskDeletionAdapter; - - @override - Future findTaskById(int id) async { - return _queryAdapter.query('SELECT * FROM task WHERE id = ?1', - mapper: (Map row) => Task( - row['id'] as int?, - row['isRead'] == null ? null : (row['isRead'] as int) != 0, - row['message'] as String, - _dateTimeConverter.decode(row['timestamp'] as int), - row['status'] == null - ? null - : TaskStatus.values[row['status'] as int], - _taskTypeConverter.decode(row['type'] as String?)), - arguments: [id]); - } - - @override - Future> findAllTasks() async { - return _queryAdapter.queryList('SELECT * FROM task', - mapper: (Map row) => Task( - row['id'] as int?, - row['isRead'] == null ? null : (row['isRead'] as int) != 0, - row['message'] as String, - _dateTimeConverter.decode(row['timestamp'] as int), - row['status'] == null - ? null - : TaskStatus.values[row['status'] as int], - _taskTypeConverter.decode(row['type'] as String?))); - } - - @override - Stream> findAllTasksAsStream() { - return _queryAdapter.queryListStream('SELECT * FROM task', - mapper: (Map row) => Task( - row['id'] as int?, - row['isRead'] == null ? null : (row['isRead'] as int) != 0, - row['message'] as String, - _dateTimeConverter.decode(row['timestamp'] as int), - row['status'] == null - ? null - : TaskStatus.values[row['status'] as int], - _taskTypeConverter.decode(row['type'] as String?)), - queryableName: 'task', - isView: false); - } - - @override - Stream findUniqueMessagesCountAsStream() { - return _queryAdapter.queryStream('SELECT DISTINCT COUNT(message) FROM task', - mapper: (Map row) => row.values.first as int, - queryableName: 'task', - isView: false); - } - - @override - Stream> findAllTasksByStatusAsStream(TaskStatus status) { - return _queryAdapter.queryListStream('SELECT * FROM task WHERE status = ?1', - mapper: (Map row) => Task( - row['id'] as int?, - row['isRead'] == null ? null : (row['isRead'] as int) != 0, - row['message'] as String, - _dateTimeConverter.decode(row['timestamp'] as int), - row['status'] == null - ? null - : TaskStatus.values[row['status'] as int], - _taskTypeConverter.decode(row['type'] as String?)), - arguments: [status.index], - queryableName: 'task', - isView: false); - } - - @override - Future updateTypeById( - TaskType type, - int id, - ) async { - return _queryAdapter.query( - 'UPDATE OR ABORT Task SET type = ?1 WHERE id = ?2', - mapper: (Map row) => row.values.first as int, - arguments: [type.index, id]); - } - - @override - Future insertTask(Task task) async { - await _taskInsertionAdapter.insert(task, OnConflictStrategy.abort); - } - - @override - Future insertTasks(List tasks) async { - await _taskInsertionAdapter.insertList(tasks, OnConflictStrategy.abort); - } - - @override - Future updateTask(Task task) async { - await _taskUpdateAdapter.update(task, OnConflictStrategy.abort); - } - - @override - Future updateTasks(List task) async { - await _taskUpdateAdapter.updateList(task, OnConflictStrategy.abort); - } - - @override - Future deleteTask(Task task) async { - await _taskDeletionAdapter.delete(task); - } - - @override - Future deleteTasks(List tasks) async { - await _taskDeletionAdapter.deleteList(tasks); - } -} - -// ignore_for_file: unused_element -final _dateTimeConverter = DateTimeConverter(); -final _taskTypeConverter = TaskTypeConverter(); diff --git a/example/lib/main.dart b/example/lib/main.dart index b0994452..63650b56 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -7,7 +7,7 @@ Future main() async { WidgetsFlutterBinding.ensureInitialized(); final database = await $FloorFlutterDatabase - .databaseBuilder('flutter_database.db') + .databaseBuilder('flutter_database.db','password') .build(); final dao = database.taskDao; diff --git a/example/pubspec.lock b/example/pubspec.lock index 841a53a7..f5fa6675 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -77,10 +77,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.4.13" build_runner_core: dependency: transitive description: @@ -223,7 +223,7 @@ packages: path: "../floor" relative: true source: path - version: "1.4.2" + version: "1.5.0" floor_annotation: dependency: transitive description: @@ -267,10 +267,10 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" glob: dependency: transitive description: @@ -339,26 +339,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: @@ -395,18 +395,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.15.0" mime: dependency: transitive description: @@ -500,14 +500,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" - sqflite: - dependency: "direct main" - description: - name: sqflite - sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 - url: "https://pub.dev" - source: hosted - version: "2.3.2" sqflite_common: dependency: transitive description: @@ -532,6 +524,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.3" + sqflite_sqlcipher: + dependency: transitive + description: + name: sqflite_sqlcipher + sha256: "16033fde6c7d7bd657b71a2bc42332ab02bc8001c3212f502d2e02714e735ec9" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" sqlite3: dependency: transitive description: @@ -608,10 +608,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" timing: dependency: transitive description: @@ -648,10 +648,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.5" watcher: dependency: transitive description: @@ -685,5 +685,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.7.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 0b074ef2..c72e4536 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: path: ../floor/ flutter: sdk: flutter - sqflite: any # This dependency is needed to solve the problem with warning about transitive dependencies + #sqflite: any # This dependency is needed to solve the problem with warning about transitive dependencies dev_dependencies: analyzer: ^6.4.1 diff --git a/floor/README.md b/floor/README.md index bb040ea3..362b6797 100644 --- a/floor/README.md +++ b/floor/README.md @@ -116,7 +116,7 @@ In this case, the file is named `database.dart`. // required package imports import 'dart:async'; import 'package:floor/floor.dart'; -import 'package:sqflite/sqflite.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqflite.dart' as sqflite; import 'dao/person_dao.dart'; import 'entity/person.dart'; diff --git a/floor/lib/src/sqflite_database_factory.dart b/floor/lib/src/sqflite_database_factory.dart index fd91e191..97e647e7 100644 --- a/floor/lib/src/sqflite_database_factory.dart +++ b/floor/lib/src/sqflite_database_factory.dart @@ -4,13 +4,15 @@ import 'package:flutter/foundation.dart'; import 'package:path/path.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart'; +import 'package:sqflite_sqlcipher/sqflite.dart' as sqlcipher; + // infers factory as nullable without explicit type definition -final DatabaseFactory sqfliteDatabaseFactory = () { +final sqlcipher.DatabaseFactory sqfliteDatabaseFactory = () { if (kIsWeb) { return databaseFactoryFfiWeb; } else if (Platform.isAndroid || Platform.isIOS) { - return databaseFactory; + return sqlcipher.databaseFactory; } else if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) { sqfliteFfiInit(); return databaseFactoryFfi; @@ -21,9 +23,9 @@ final DatabaseFactory sqfliteDatabaseFactory = () { } }(); -extension DatabaseFactoryExtension on DatabaseFactory { +extension DatabaseFactoryExtension on sqlcipher.DatabaseFactory { Future getDatabasePath(final String name) async { - final databasesPath = await this.getDatabasesPath(); + final databasesPath = await getDatabasesPath(); return join(databasesPath, name); } } diff --git a/floor/pubspec.lock b/floor/pubspec.lock index b8f2496b..cd092a62 100644 --- a/floor/pubspec.lock +++ b/floor/pubspec.lock @@ -324,26 +324,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lists: dependency: transitive description: @@ -372,18 +372,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: "direct main" description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.15.0" mime: dependency: transitive description: @@ -485,14 +485,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" - sqflite: - dependency: "direct main" - description: - name: sqflite - sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 - url: "https://pub.dev" - source: hosted - version: "2.3.2" sqflite_common: dependency: transitive description: @@ -517,6 +509,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.3" + sqflite_sqlcipher: + dependency: "direct main" + description: + name: sqflite_sqlcipher + sha256: "16033fde6c7d7bd657b71a2bc42332ab02bc8001c3212f502d2e02714e735ec9" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" sqlite3: dependency: transitive description: @@ -593,10 +593,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" timing: dependency: transitive description: @@ -633,10 +633,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.5" watcher: dependency: transitive description: @@ -671,4 +671,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.3.0 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.19.0" diff --git a/floor/pubspec.yaml b/floor/pubspec.yaml index eaec378c..7240446d 100644 --- a/floor/pubspec.yaml +++ b/floor/pubspec.yaml @@ -21,7 +21,8 @@ dependencies: sdk: flutter meta: path: ^1.9.0 - sqflite: ^2.3.2 + # sqflite: ^2.3.2 + sqflite_sqlcipher: ^3.1.0+1 sqflite_common_ffi: ^2.3.2+1 sqflite_common_ffi_web: ^0.4.3 sqlparser: ^0.34.1 diff --git a/floor_common/lib/src/adapter/deletion_adapter.dart b/floor_common/lib/src/adapter/deletion_adapter.dart index 9a5b1721..3ffc640e 100644 --- a/floor_common/lib/src/adapter/deletion_adapter.dart +++ b/floor_common/lib/src/adapter/deletion_adapter.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/src/util/primary_key_helper.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; class DeletionAdapter { final DatabaseExecutor _database; diff --git a/floor_common/lib/src/adapter/insertion_adapter.dart b/floor_common/lib/src/adapter/insertion_adapter.dart index af154a88..80b5f6f1 100644 --- a/floor_common/lib/src/adapter/insertion_adapter.dart +++ b/floor_common/lib/src/adapter/insertion_adapter.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:floor_annotation/floor_annotation.dart'; import 'package:floor_common/src/extension/on_conflict_strategy_extensions.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; class InsertionAdapter { final DatabaseExecutor _database; diff --git a/floor_common/lib/src/adapter/migration_adapter.dart b/floor_common/lib/src/adapter/migration_adapter.dart index 58d98a52..23a0e096 100644 --- a/floor_common/lib/src/adapter/migration_adapter.dart +++ b/floor_common/lib/src/adapter/migration_adapter.dart @@ -1,5 +1,5 @@ import 'package:floor_common/src/migration.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; // ignore: avoid_classes_with_only_static_members abstract class MigrationAdapter { diff --git a/floor_common/lib/src/adapter/query_adapter.dart b/floor_common/lib/src/adapter/query_adapter.dart index 34c2cf6d..08ef0490 100644 --- a/floor_common/lib/src/adapter/query_adapter.dart +++ b/floor_common/lib/src/adapter/query_adapter.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; import 'package:collection/collection.dart'; import 'package:floor_common/src/util/string_utils.dart'; diff --git a/floor_common/lib/src/adapter/update_adapter.dart b/floor_common/lib/src/adapter/update_adapter.dart index a39a8c75..025b6a90 100644 --- a/floor_common/lib/src/adapter/update_adapter.dart +++ b/floor_common/lib/src/adapter/update_adapter.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:floor_annotation/floor_annotation.dart'; import 'package:floor_common/src/extension/on_conflict_strategy_extensions.dart'; import 'package:floor_common/src/util/primary_key_helper.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; class UpdateAdapter { final DatabaseExecutor _database; diff --git a/floor_common/lib/src/callback.dart b/floor_common/lib/src/callback.dart index 9a25ef7a..a4289b47 100644 --- a/floor_common/lib/src/callback.dart +++ b/floor_common/lib/src/callback.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; /// Callback class that can be attached to the Floor builder. class Callback { diff --git a/floor_common/lib/src/database.dart b/floor_common/lib/src/database.dart index 5baf0237..a863c856 100644 --- a/floor_common/lib/src/database.dart +++ b/floor_common/lib/src/database.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:meta/meta.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; /// Extend this class to enable database functionality. abstract class FloorDatabase { diff --git a/floor_common/lib/src/extension/on_conflict_strategy_extensions.dart b/floor_common/lib/src/extension/on_conflict_strategy_extensions.dart index 13898261..e1eb12d6 100644 --- a/floor_common/lib/src/extension/on_conflict_strategy_extensions.dart +++ b/floor_common/lib/src/extension/on_conflict_strategy_extensions.dart @@ -1,5 +1,5 @@ import 'package:floor_annotation/floor_annotation.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; extension OnConflictStrategyExtensions on OnConflictStrategy { ConflictAlgorithm asSqfliteConflictAlgorithm() { diff --git a/floor_common/lib/src/migration.dart b/floor_common/lib/src/migration.dart index 8eac3722..987b7a30 100644 --- a/floor_common/lib/src/migration.dart +++ b/floor_common/lib/src/migration.dart @@ -1,4 +1,4 @@ -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; /// Base class for a database migration. /// diff --git a/floor_common/pubspec.lock b/floor_common/pubspec.lock index d772245d..15b046bd 100644 --- a/floor_common/pubspec.lock +++ b/floor_common/pubspec.lock @@ -77,10 +77,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.4.11" build_runner_core: dependency: transitive description: @@ -215,14 +215,19 @@ packages: relative: true source: path version: "1.4.2" - frontend_server_client: + flutter: dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: "direct main" description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" glob: dependency: transitive description: @@ -303,14 +308,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" meta: dependency: "direct main" description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.15.0" mime: dependency: transitive description: @@ -407,6 +420,11 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" source_gen: dependency: transitive description: @@ -440,7 +458,7 @@ packages: source: hosted version: "1.10.0" sqflite_common: - dependency: "direct main" + dependency: transitive description: name: sqflite_common sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" @@ -455,6 +473,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.3" + sqflite_sqlcipher: + dependency: "direct main" + description: + name: sqflite_sqlcipher + sha256: "16033fde6c7d7bd657b71a2bc42332ab02bc8001c3212f502d2e02714e735ec9" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" sqlite3: dependency: transitive description: @@ -575,6 +601,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" vm_service: dependency: transitive description: @@ -624,4 +658,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0 <4.0.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/floor_common/pubspec.yaml b/floor_common/pubspec.yaml index d4a78d8c..5862c388 100644 --- a/floor_common/pubspec.yaml +++ b/floor_common/pubspec.yaml @@ -14,8 +14,10 @@ dependencies: path: ../floor_annotation/ meta: path: ^1.9.0 - sqflite_common: ^2.5.3 + # sqflite_common: ^2.5.3 sqlparser: ^0.34.1 + sqflite_sqlcipher: ^3.0.0 + frontend_server_client: ^4.0.0 dev_dependencies: build_runner: ^2.4.8 diff --git a/floor_common/test/adapter/insertion_adapter_test.dart b/floor_common/test/adapter/insertion_adapter_test.dart index f8776d48..8f560e4e 100644 --- a/floor_common/test/adapter/insertion_adapter_test.dart +++ b/floor_common/test/adapter/insertion_adapter_test.dart @@ -1,6 +1,6 @@ import 'package:floor_common/floor_common.dart'; import 'package:mockito/mockito.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; import 'package:test/test.dart'; import '../test_util/mocks.dart'; diff --git a/floor_common/test/adapter/update_adapter_test.dart b/floor_common/test/adapter/update_adapter_test.dart index 5a91f370..5209b220 100644 --- a/floor_common/test/adapter/update_adapter_test.dart +++ b/floor_common/test/adapter/update_adapter_test.dart @@ -1,6 +1,6 @@ import 'package:floor_common/floor_common.dart'; import 'package:mockito/mockito.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; import 'package:test/test.dart'; import '../test_util/mocks.dart'; diff --git a/floor_common/test/extension/on_conflict_strategy_extensions_test.dart b/floor_common/test/extension/on_conflict_strategy_extensions_test.dart index 7183bbfb..fe5468ab 100644 --- a/floor_common/test/extension/on_conflict_strategy_extensions_test.dart +++ b/floor_common/test/extension/on_conflict_strategy_extensions_test.dart @@ -1,6 +1,6 @@ import 'package:floor_common/floor_common.dart'; import 'package:floor_common/src/extension/on_conflict_strategy_extensions.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; import 'package:test/test.dart'; void main() { diff --git a/floor_common/test/integration/autoincrement/autoinc_test.dart b/floor_common/test/integration/autoincrement/autoinc_test.dart index 6d90351a..407180ba 100644 --- a/floor_common/test/integration/autoincrement/autoinc_test.dart +++ b/floor_common/test/integration/autoincrement/autoinc_test.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import 'package:test/test.dart'; import '../../test_util/database_factory.dart'; diff --git a/floor_common/test/integration/blob/blob_test.dart b/floor_common/test/integration/blob/blob_test.dart index 9ac9f7f3..4d8b4a51 100644 --- a/floor_common/test/integration/blob/blob_test.dart +++ b/floor_common/test/integration/blob/blob_test.dart @@ -3,7 +3,7 @@ import 'dart:typed_data'; import 'package:collection/collection.dart'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import 'package:test/test.dart'; import '../../test_util/database_factory.dart'; diff --git a/floor_common/test/integration/boolean_conversions/bool_test.dart b/floor_common/test/integration/boolean_conversions/bool_test.dart index 63daa368..d170364d 100644 --- a/floor_common/test/integration/boolean_conversions/bool_test.dart +++ b/floor_common/test/integration/boolean_conversions/bool_test.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import 'package:test/test.dart'; import '../../test_util/database_factory.dart'; diff --git a/floor_common/test/integration/database.dart b/floor_common/test/integration/database.dart index 5b73f708..4b48d34f 100644 --- a/floor_common/test/integration/database.dart +++ b/floor_common/test/integration/database.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import '../test_util/database_factory.dart'; import 'dao/dog_dao.dart'; diff --git a/floor_common/test/integration/database_test.dart b/floor_common/test/integration/database_test.dart index 28dfe5cc..7e55f1fe 100644 --- a/floor_common/test/integration/database_test.dart +++ b/floor_common/test/integration/database_test.dart @@ -1,5 +1,5 @@ import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; import 'package:test/test.dart'; import '../test_util/extensions.dart'; diff --git a/floor_common/test/integration/fts/mail_database.dart b/floor_common/test/integration/fts/mail_database.dart index 631ad9fc..effcdfa5 100644 --- a/floor_common/test/integration/fts/mail_database.dart +++ b/floor_common/test/integration/fts/mail_database.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import '../../test_util/database_factory.dart'; import 'mail.dart'; diff --git a/floor_common/test/integration/inheritance/dao_inheritance_test.dart b/floor_common/test/integration/inheritance/dao_inheritance_test.dart index e2d2c087..b51648a1 100644 --- a/floor_common/test/integration/inheritance/dao_inheritance_test.dart +++ b/floor_common/test/integration/inheritance/dao_inheritance_test.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; import 'package:test/test.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import '../../test_util/database_factory.dart'; diff --git a/floor_common/test/integration/inheritance/entity_inheritance_test.dart b/floor_common/test/integration/inheritance/entity_inheritance_test.dart index 9fd74438..47a884a6 100644 --- a/floor_common/test/integration/inheritance/entity_inheritance_test.dart +++ b/floor_common/test/integration/inheritance/entity_inheritance_test.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import 'package:test/test.dart'; import '../../test_util/database_factory.dart'; diff --git a/floor_common/test/integration/type_converter/order_database.dart b/floor_common/test/integration/type_converter/order_database.dart index 5cdfd1c3..34a4a900 100644 --- a/floor_common/test/integration/type_converter/order_database.dart +++ b/floor_common/test/integration/type_converter/order_database.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import '../../test_util/database_factory.dart'; import 'order.dart'; diff --git a/floor_common/test/integration/view/view_test.dart b/floor_common/test/integration/view/view_test.dart index a1f0c96f..de824397 100644 --- a/floor_common/test/integration/view/view_test.dart +++ b/floor_common/test/integration/view/view_test.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:floor_common/floor_common.dart'; -import 'package:sqflite_common/sqlite_api.dart' as sqflite; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as sqflite; import 'package:test/test.dart'; import '../../test_util/database_factory.dart'; diff --git a/floor_common/test/test_util/database_factory.dart b/floor_common/test/test_util/database_factory.dart index 7f4ee9c1..ee547c3f 100644 --- a/floor_common/test/test_util/database_factory.dart +++ b/floor_common/test/test_util/database_factory.dart @@ -1,5 +1,5 @@ import 'package:path/path.dart'; -import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_sqlcipher/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; // infers factory as nullable without explicit type definition diff --git a/floor_common/test/test_util/mocks.dart b/floor_common/test/test_util/mocks.dart index 3086faaa..ec57617c 100644 --- a/floor_common/test/test_util/mocks.dart +++ b/floor_common/test/test_util/mocks.dart @@ -1,7 +1,7 @@ import 'dart:async' as _i3; import 'package:mockito/mockito.dart' as _i1; -import 'package:sqflite_common/sqlite_api.dart' as _i2; +import 'package:sqflite_sqlcipher/sqlite_api.dart' as _i2; import 'package:sqflite_common/src/sql_builder.dart' as _i4; // ignore_for_file: comment_references diff --git a/floor_generator/lib/writer/database_builder_writer.dart b/floor_generator/lib/writer/database_builder_writer.dart index f26043cc..225548fd 100644 --- a/floor_generator/lib/writer/database_builder_writer.dart +++ b/floor_generator/lib/writer/database_builder_writer.dart @@ -5,8 +5,7 @@ import 'package:floor_generator/writer/writer.dart'; class DatabaseBuilderWriter extends Writer { final String _databaseName; - DatabaseBuilderWriter(final String databaseName) - : _databaseName = databaseName; + DatabaseBuilderWriter(final String databaseName) : _databaseName = databaseName; @override Class write() { @@ -20,6 +19,11 @@ class DatabaseBuilderWriter extends Writer { ..type = refer('String?') ..modifier = FieldModifier.final$); + final passwordField = Field((builder) => builder + ..name = 'password' + ..type = refer('String?') + ..modifier = FieldModifier.final$); + final migrationsField = Field((builder) => builder ..name = '_migrations' ..type = refer('List') @@ -33,7 +37,10 @@ class DatabaseBuilderWriter extends Writer { final constructor = Constructor((builder) => builder ..requiredParameters.add(Parameter((builder) => builder ..toThis = true - ..name = 'name'))); + ..name = 'name')) + ..optionalParameters.add(Parameter((builder) => builder + ..toThis = true + ..name = 'password'))); final addMigrationsMethod = Method((builder) => builder ..annotations.add(overrideAnnotationExpression) @@ -71,6 +78,7 @@ class DatabaseBuilderWriter extends Writer { final database = _\$$_databaseName(); database.database = await database.open( path, + password, _migrations, _callback, ); @@ -84,6 +92,7 @@ class DatabaseBuilderWriter extends Writer { ]) ..fields.addAll([ nameField, + passwordField, migrationsField, callbackField, ]) diff --git a/floor_generator/lib/writer/database_writer.dart b/floor_generator/lib/writer/database_writer.dart index 8948814a..2dcbf1d2 100644 --- a/floor_generator/lib/writer/database_writer.dart +++ b/floor_generator/lib/writer/database_writer.dart @@ -19,7 +19,8 @@ class DatabaseWriter implements Writer { Class _generateDatabaseImplementation(final Database database) { final databaseName = database.name; - return Class((builder) => builder + return Class((builder) => + builder ..name = '_\$$databaseName' ..extend = refer(databaseName) ..methods.add(_generateOpenMethod(database)) @@ -30,7 +31,8 @@ class DatabaseWriter implements Writer { Constructor _generateConstructor() { return Constructor((builder) { - final parameter = Parameter((builder) => builder + final parameter = Parameter((builder) => + builder ..name = 'listener' ..type = refer('StreamController?')); @@ -47,7 +49,8 @@ class DatabaseWriter implements Writer { final daoGetterName = daoGetter.name; final daoTypeName = daoGetter.dao.classElement.displayName; - return Method((builder) => builder + return Method((builder) => + builder ..annotations.add(overrideAnnotationExpression) ..type = MethodType.getter ..returns = refer(daoTypeName) @@ -62,7 +65,8 @@ class DatabaseWriter implements Writer { final daoGetterName = daoGetter.name; final daoTypeName = daoGetter.dao.classElement.displayName; - return Field((builder) => builder + return Field((builder) => + builder ..type = refer('$daoTypeName?') ..name = '_${daoGetterName}Instance'); }).toList(); @@ -70,7 +74,7 @@ class DatabaseWriter implements Writer { Method _generateOpenMethod(final Database database) { final createTableStatements = _generateCreateTableSqlStatements( - database.entities) + database.entities) .map((statement) => 'await database.execute(${statement.toLiteral()});') .join('\n'); final createIndexStatements = database.entities @@ -83,24 +87,33 @@ class DatabaseWriter implements Writer { .map((statement) => 'await database.execute($statement);') .join('\n'); - final pathParameter = Parameter((builder) => builder + final pathParameter = Parameter((builder) => + builder ..name = 'path' ..type = refer('String')); - final migrationsParameter = Parameter((builder) => builder + final passwordParameter = Parameter((builder) => + builder + ..name = 'password' + ..type = refer('String?')); + final migrationsParameter = Parameter((builder) => + builder ..name = 'migrations' ..type = refer('List')); - final callbackParameter = Parameter((builder) => builder + final callbackParameter = Parameter((builder) => + builder ..name = 'callback' ..type = refer('Callback?')); - return Method((builder) => builder + return Method((builder) => + builder ..name = 'open' ..returns = refer('Future') ..modifier = MethodModifier.async - ..requiredParameters.addAll([pathParameter, migrationsParameter]) + ..requiredParameters.addAll([pathParameter, passwordParameter, migrationsParameter]) ..optionalParameters.add(callbackParameter) ..body = Code(''' - final databaseOptions = sqflite.OpenDatabaseOptions( + final databaseOptions = sqflite.SqlCipherOpenDatabaseOptions( + password: password, version: ${database.version}, onConfigure: (database) async { await database.execute('PRAGMA foreign_keys = ON'); diff --git a/floor_generator/lib/writer/floor_writer.dart b/floor_generator/lib/writer/floor_writer.dart index 674a41d2..90ceb744 100644 --- a/floor_generator/lib/writer/floor_writer.dart +++ b/floor_generator/lib/writer/floor_writer.dart @@ -25,7 +25,11 @@ class FloorWriter extends Writer { ]) ..requiredParameters.add(Parameter((builder) => builder ..name = 'name' - ..type = refer('String')))); + ..type = refer('String'))) + ..requiredParameters.add(Parameter((builder) => builder + ..name = 'password' + ..type = refer('String'))) + ..body = Code('$databaseBuilderName(name, password)')); final inMemoryDatabaseBuilderMethod = Method((builder) => builder ..name = 'inMemoryDatabaseBuilder' diff --git a/floor_generator/pubspec.yaml b/floor_generator/pubspec.yaml index ba572593..b8d5a7b3 100644 --- a/floor_generator/pubspec.yaml +++ b/floor_generator/pubspec.yaml @@ -23,6 +23,7 @@ dependencies: source_gen: ^1.5.0 strings: ^3.1.1 + dev_dependencies: build_test: ^2.2.2 dart_style: ^2.3.4 diff --git a/floor_generator/test/writer/database_builder_writer_test.dart b/floor_generator/test/writer/database_builder_writer_test.dart index 72f8e07c..f1696d8f 100644 --- a/floor_generator/test/writer/database_builder_writer_test.dart +++ b/floor_generator/test/writer/database_builder_writer_test.dart @@ -14,9 +14,10 @@ void main() { expect(actual, equalsDart(r''' class _$FooBarBuilder implements $FooBarBuilderContract { - _$FooBarBuilder(this.name); + _$FooBarBuilder(this.name, this.password); final String? name; + final String password; final List _migrations = []; @@ -42,6 +43,7 @@ void main() { final database = _$FooBar(); database.database = await database.open( path, + password, _migrations, _callback, ); diff --git a/floor_generator/test/writer/database_writer_test.dart b/floor_generator/test/writer/database_writer_test.dart index 98224c0b..56a3e5e3 100644 --- a/floor_generator/test/writer/database_writer_test.dart +++ b/floor_generator/test/writer/database_writer_test.dart @@ -36,11 +36,13 @@ void main() { } Future open( - String path, - List migrations, [ - Callback? callback, + String path, + String password, + List migrations, [ + Callback? callback, String password ]) async { final databaseOptions = sqflite.OpenDatabaseOptions( + password: password, version: 1, onConfigure: (database) async { await database.execute('PRAGMA foreign_keys = ON'); @@ -62,7 +64,7 @@ void main() { await callback?.onCreate?.call(database, version); }, ); - return sqfliteDatabaseFactory.openDatabase(path, options: databaseOptions); + return sqfliteDatabaseFactory.openDatabase(path, password, options: databaseOptions); } } ''')); @@ -104,10 +106,12 @@ void main() { Future open( String path, + String password, List migrations, [ Callback? callback, ]) async { final databaseOptions = sqflite.OpenDatabaseOptions( + password: password, version: 1, onConfigure: (database) async { await database.execute('PRAGMA foreign_keys = ON'); @@ -167,10 +171,12 @@ void main() { Future open( String path, + String password, List migrations, [ - Callback? callback, + Callback? callback ]) async { final databaseOptions = sqflite.OpenDatabaseOptions( + password: password, version: 1, onConfigure: (database) async { await database.execute('PRAGMA foreign_keys = ON'); @@ -233,10 +239,12 @@ void main() { Future open( String path, + String password, List migrations, [ - Callback? callback, + Callback? callback ]) async { final databaseOptions = sqflite.OpenDatabaseOptions( + password: password, version: 1, onConfigure: (database) async { await database.execute('PRAGMA foreign_keys = ON');