From 921d83c300e37b441c170e66889c974e02cc7f7d Mon Sep 17 00:00:00 2001 From: Vitus Ortner Date: Sat, 23 Feb 2019 10:17:09 +0100 Subject: [PATCH 1/7] WIP documentation --- README.md | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b816e79..c9872ff9 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,159 @@ # Floor **A supportive SQLite abstraction for your Flutter applications.** -This package is in a very early development stage. Better not use it. +This package is under heavy development and the API will likely change. +## How to use this library +1. Add the runtime dependency `floor` as well as the generator `floor_generator` to your `pubspec.yaml`. + The third dependency is `build_runner` which has to be included as a dev dependency just like the generator. + + - `floor` holds all the code you are going to use in your application. + + - `floor_generator` includes the code for generating the database classes. + + - `build_runner` enables a concrete way of generating source code files. + + ````yaml + dependencies: + flutter: + sdk: flutter + floor: + git: + url: https://github.com/vitusortner/floor.git + path: /floor + + dev_dependencies: + flutter_test: + sdk: flutter + floor_generator: + git: + url: https://github.com/vitusortner/floor.git + path: /floor_generator + build_runner: ^1.1.3 + ```` + +1. Make sure to import the following libraries. + + ```dart + import 'package:floor/floor.dart'; + import 'package:path/path.dart'; + import 'package:sqflite/sqflite.dart' as sqflite; + ``` + +1. Create an `Entity`. + It will represent a database table as well as the scaffold of your business object. + `@Entity()` marks the class as a persistent class. + It's required to add a primary key to your table. + You can do so by adding the `@PrimarKey()` annotation to an `int` property. + + ````dart + @Entity() + class Person { + @PrimaryKey() + final int id; + + final String name; + + Person(this.id, this.name); + } + ```` + +1. Create the `Database`. + This component is responsible for managing the access to the underlying SQLite database. + It has to be an abstract class which extends `FloorDatabase`. + Furthermore, it's required to add `@Database()` to the signature of the class. + + This class contains the method signatures for querying the database which have to return a `Future`. + It, moreover, holds functionality for opening the database. + `_$open()` is a function that will get implemented by running the code generator. + The warning, of it not being implemented, will go away then. + + - You can define queries by adding the `@Query` annotation to a method. + The SQL statement has to get added in parenthesis. + The method must return a `Future` of the `Entity` you're querying for. + + - `@insert` marks a method as an insertion method. + + ```dart + @Database() + abstract class AppDatabase extends FloorDatabase { + static Future openDatabase() async => _$open(); + + @Query('SELECT * FROM Person') + Future> findAllPersons(); + + @Query('SELECT * FROM Person WHERE id = :id') + Future findPersonById(int id); + + @insert + Future insertPerson(Person person); + } + ``` + +1. Add `part 'database.g.dart';` beneath the imports of this file. + It's important to note, that 'database' has to get exchanged with the name of the file the entity and database is defined in. + In this case the file is named `database.dart`. + +1. Run the generator with `flutter packages pub run build_runner build`. + To automatically run it, whenever a file changes, use `flutter packages pub run build_runner watch`. + +1. Use the generated code. + +For further examples take a look at the `example` and `floor_test` directories. + + +## Querying +Method signatures turn into query methods by adding the `@Query()` annotation with the query in parenthesis to them. +Be patient about your SQL statements. +The are only partly validated while generating the code. + +````dart +@Query('SELECT * FROM Person WHERE id = :id') +Future findPersonById(int id); + +@Query('SELECT * FROM Person WHERE id = :id AND name = :name') +Future findPersonByIdAndName(int id, String name); + +@Query('SELECT * FROM Person') +Future> findAllPersons(); // select multiple items +```` + +## Persisting Data Changes +- `@insert` marks a method as an insertion method. + It accepts a single but also multiple items as input. + These methods can return a `Future` of either `void`, `int` or `List`. + - `void` return nothing + - `int` return primary key of inserted item + - `List` return primary keys of inserted items + +- `@update` marks a method as an update method. + It accepts a single but also multiple items as input. + These methods can return a `Future` of either `void`, `int` or `List`. + - `void` return nothing + - `int` return number of changed rows + - `List` return number of changed rows + +- `@delete` marks a method as a deletion method. + It accepts a single but also multiple items as input. + These methods can return a `Future` of either `void`, `int` or `List`. + - `void` return nothing + - `int` return number of deleted rows + - `List` return number of deleted rows + +```dart +// examples of changing multiple items with return + +@insert +Future> insertPersons(List person); + +@update +Future> updatePersons(List person); + +@delete +Future> deletePersons(List person); +``` + +## Naming *Floor - the bottom layer of a [Room](https://developer.android.com/topic/libraries/architecture/room).* ## Bugs and Feedback From 0d230b69955d964ef84f8713a82063843604fa4b Mon Sep 17 00:00:00 2001 From: Vitus Ortner Date: Sat, 23 Feb 2019 10:23:12 +0100 Subject: [PATCH 2/7] WIP documentation --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index c9872ff9..aef13df8 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,15 @@ This package is under heavy development and the API will likely change. To automatically run it, whenever a file changes, use `flutter packages pub run build_runner watch`. 1. Use the generated code. + +```dart +final database = await AppDatabase.openDatabase(); + +final person = await database.findPersonById(1); +await database.insertPerson(person); +await database.updatePerson(person); +await database.deletePerson(person); +``` For further examples take a look at the `example` and `floor_test` directories. From 9a1733ede00336dec2dec3ab3d76a46762801c7e Mon Sep 17 00:00:00 2001 From: Vitus Ortner Date: Sat, 23 Feb 2019 10:42:54 +0100 Subject: [PATCH 3/7] WIP documentation --- README.md | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index aef13df8..c324c1a6 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,12 @@ This package is under heavy development and the API will likely change. +1. [How to use this library](#how-to-use-this-library) +1. [Querying](#querying) +1. [Persisting Data Changes](#persisting-data-changes) +1. [Transactions](#transactions) +1. [Foreign Keys](#foreign-keys) + ## How to use this library 1. Add the runtime dependency `floor` as well as the generator `floor_generator` to your `pubspec.yaml`. The third dependency is `build_runner` which has to be included as a dev dependency just like the generator. @@ -99,16 +105,16 @@ This package is under heavy development and the API will likely change. 1. Use the generated code. -```dart -final database = await AppDatabase.openDatabase(); + ```dart + final database = await AppDatabase.openDatabase(); -final person = await database.findPersonById(1); -await database.insertPerson(person); -await database.updatePerson(person); -await database.deletePerson(person); -``` + final person = await database.findPersonById(1); + await database.insertPerson(person); + await database.updatePerson(person); + await database.deletePerson(person); + ``` -For further examples take a look at the `example` and `floor_test` directories. +For further examples take a look at the [example](https://github.com/vitusortner/floor/tree/develop/example) and [floor_test](https://github.com/vitusortner/floor/tree/develop/floor_test) directories. ## Querying @@ -161,6 +167,20 @@ Future> updatePersons(List person); @delete Future> deletePersons(List person); ``` + +## Transactions +Whenever you want to perform some operations in a transaction you have to add the `@transaction` annotation to the method. +It also requires to add the `async` modifier. These methods can only return `Future`. + +```dart +@transaction +Future replacePersons(List persons) async { + await database.execute('DELETE FROM Person'); + await insertPersons(persons); +} +``` + +## Foreign Keys ## Naming *Floor - the bottom layer of a [Room](https://developer.android.com/topic/libraries/architecture/room).* From 6bee242cad3b6e9fc02b7ee7183cdf6751253732 Mon Sep 17 00:00:00 2001 From: Vitus Ortner Date: Sat, 23 Feb 2019 13:43:53 +0100 Subject: [PATCH 4/7] WIP documentation --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c324c1a6..a57065e1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Floor **A supportive SQLite abstraction for your Flutter applications.** -This package is under heavy development and the API will likely change. +This package is still under development and the API will likely change. 1. [How to use this library](#how-to-use-this-library) 1. [Querying](#querying) @@ -26,7 +26,7 @@ This package is under heavy development and the API will likely change. floor: git: url: https://github.com/vitusortner/floor.git - path: /floor + path: /floor/ dev_dependencies: flutter_test: @@ -34,7 +34,7 @@ This package is under heavy development and the API will likely change. floor_generator: git: url: https://github.com/vitusortner/floor.git - path: /floor_generator + path: /floor_generator/ build_runner: ^1.1.3 ```` @@ -175,6 +175,7 @@ It also requires to add the `async` modifier. These methods can only return `Fut ```dart @transaction Future replacePersons(List persons) async { + // execute SQL without automatically generated code await database.execute('DELETE FROM Person'); await insertPersons(persons); } From 11e9eb0034d51cc9b8a2cab6375ff3a235119078 Mon Sep 17 00:00:00 2001 From: Vitus Ortner Date: Sat, 23 Feb 2019 14:50:22 +0100 Subject: [PATCH 5/7] WIP documentation --- README.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a57065e1..8e3a88ee 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,19 @@ # Floor **A supportive SQLite abstraction for your Flutter applications.** +The Floor library provides a lightweight SQLite abstraction with automatic mapping between in-memory objects and database rows while still offering full control of the database with the use of SQL. + This package is still under development and the API will likely change. +### Table of contents + 1. [How to use this library](#how-to-use-this-library) 1. [Querying](#querying) 1. [Persisting Data Changes](#persisting-data-changes) 1. [Transactions](#transactions) +1. [Entities](#entities) 1. [Foreign Keys](#foreign-keys) +1. [Examples](#examples) ## How to use this library 1. Add the runtime dependency `floor` as well as the generator `floor_generator` to your `pubspec.yaml`. @@ -115,12 +121,12 @@ This package is still under development and the API will likely change. ``` For further examples take a look at the [example](https://github.com/vitusortner/floor/tree/develop/example) and [floor_test](https://github.com/vitusortner/floor/tree/develop/floor_test) directories. - ## Querying Method signatures turn into query methods by adding the `@Query()` annotation with the query in parenthesis to them. -Be patient about your SQL statements. +Be patient about the correctness of your SQL statements. The are only partly validated while generating the code. +These queries have to return an entity. ````dart @Query('SELECT * FROM Person WHERE id = :id') @@ -134,26 +140,30 @@ Future> findAllPersons(); // select multiple items ```` ## Persisting Data Changes -- `@insert` marks a method as an insertion method. - It accepts a single but also multiple items as input. +Use the `@insert`, `@update` and `@delete` annotations for inserting and changing persistent data. +All these methods accept single or multiple entity instances. + +- **Insert** + + `@insert` marks a method as an insertion method. These methods can return a `Future` of either `void`, `int` or `List`. - `void` return nothing - `int` return primary key of inserted item - `List` return primary keys of inserted items -- `@update` marks a method as an update method. - It accepts a single but also multiple items as input. - These methods can return a `Future` of either `void`, `int` or `List`. +- **Update** + + `@update` marks a method as an update method. + These methods can return a `Future` of either `void` or `int`. - `void` return nothing - `int` return number of changed rows - - `List` return number of changed rows -- `@delete` marks a method as a deletion method. - It accepts a single but also multiple items as input. - These methods can return a `Future` of either `void`, `int` or `List`. +- **Delete** + + `@delete` marks a method as a deletion method. + These methods can return a `Future` of either `void` or `int`. - `void` return nothing - `int` return number of deleted rows - - `List` return number of deleted rows ```dart // examples of changing multiple items with return @@ -181,15 +191,73 @@ Future replacePersons(List persons) async { } ``` +## Entities +An entity is a persistent class. +Floor automatically creates the mappings between the in-memory objects and database table rows. +It's possible to supply custom metadata to Floor by adding optional values to the `Entity` annotation. +It has the additional attribute of `tableName` which opens up the possibility to use a custom name for that specific entity instead of using the class name. +Another attribute `foreignKeys` allows to add foreign keys to the entity. +More information on how to use these can be found in the [Foreign Keys](#foreign-keys) section. + +`@PrimaryKey` marks a property of a class as the primary key column. +This property has to be of type int. +The value can be automatically generated by SQLite when `autoGenerate` is enabled. + +`@ColumnInfo` enables custom mapping of single table columns. +With the annotation it's possible to give columns a custom name and define if the column is able to store `null`. + +```dart +@Entity(tableName: 'person') +class Person { + @PrimaryKey() + final int id; + + @ColumnInfo(name: 'custom_name', nullable: false) + final String name; + + Person(this.id, this.name); +} +``` + ## Foreign Keys +Add a list of `ForeignKey`s to the `Entity` annotation of the referencing entity. +`childColumns` define the columns of the current entity, whereas `parentColumns` define the columns of the parent entity. +Foreign key actions can get triggered after defining them for the `onUpdate` and `onDelete` properties. + +```dart +@Entity( + tableName: 'dog', + foreignKeys: [ + ForeignKey( + childColumns: ['owner_id'], + parentColumns: ['id'], + entity: Person, + ) + ], +) +class Dog { + @PrimaryKey() + final int id; + + final String name; + + @ColumnInfo(name: 'owner_id') + final int ownerId; + + Dog(this.id, this.name, this.ownerId); +} +``` + +## Examples +For further examples take a look at the [example](https://github.com/vitusortner/floor/tree/develop/example) and [floor_test](https://github.com/vitusortner/floor/tree/develop/floor_test) directories. -## Naming +### Naming *Floor - the bottom layer of a [Room](https://developer.android.com/topic/libraries/architecture/room).* -## Bugs and Feedback +### Bugs and Feedback For bugs, questions and discussions please use the [Github Issues](https://github.com/vitusortner/floor/issues). -## License +### License Copyright 2019 Vitus Ortner Licensed under the Apache License, Version 2.0 (the "License"); From b55f11e5ecee93f26172bf1fe80bf4c927b06d45 Mon Sep 17 00:00:00 2001 From: Vitus Ortner Date: Sat, 23 Feb 2019 17:17:33 +0100 Subject: [PATCH 6/7] WIP documentation --- README.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 8e3a88ee..a9c68968 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ The Floor library provides a lightweight SQLite abstraction with automatic mapping between in-memory objects and database rows while still offering full control of the database with the use of SQL. -This package is still under development and the API will likely change. +This package is still under active development and the API will likely change. ### Table of contents @@ -14,6 +14,9 @@ This package is still under development and the API will likely change. 1. [Entities](#entities) 1. [Foreign Keys](#foreign-keys) 1. [Examples](#examples) +1. [Naming](#naming) +1. [Bugs and Feedback](#bugs-and-feedback) +1. [License](#license) ## How to use this library 1. Add the runtime dependency `floor` as well as the generator `floor_generator` to your `pubspec.yaml`. @@ -116,8 +119,6 @@ This package is still under development and the API will likely change. final person = await database.findPersonById(1); await database.insertPerson(person); - await database.updatePerson(person); - await database.deletePerson(person); ``` For further examples take a look at the [example](https://github.com/vitusortner/floor/tree/develop/example) and [floor_test](https://github.com/vitusortner/floor/tree/develop/floor_test) directories. @@ -172,15 +173,15 @@ All these methods accept single or multiple entity instances. Future> insertPersons(List person); @update -Future> updatePersons(List person); +Future updatePersons(List person); @delete -Future> deletePersons(List person); +Future deletePersons(List person); ``` ## Transactions Whenever you want to perform some operations in a transaction you have to add the `@transaction` annotation to the method. -It also requires to add the `async` modifier. These methods can only return `Future`. +It's also required to add the `async` modifier. These methods can only return `Future`. ```dart @transaction @@ -209,7 +210,7 @@ With the annotation it's possible to give columns a custom name and define if th ```dart @Entity(tableName: 'person') class Person { - @PrimaryKey() + @PrimaryKey(autoGenerate: true) final int id; @ColumnInfo(name: 'custom_name', nullable: false) @@ -250,14 +251,14 @@ class Dog { ## Examples For further examples take a look at the [example](https://github.com/vitusortner/floor/tree/develop/example) and [floor_test](https://github.com/vitusortner/floor/tree/develop/floor_test) directories. - -### Naming + +## Naming *Floor - the bottom layer of a [Room](https://developer.android.com/topic/libraries/architecture/room).* -### Bugs and Feedback +## Bugs and Feedback For bugs, questions and discussions please use the [Github Issues](https://github.com/vitusortner/floor/issues). -### License +## License Copyright 2019 Vitus Ortner Licensed under the Apache License, Version 2.0 (the "License"); From b1eaa11779ae850fe261fc4ac634822eba67a3d6 Mon Sep 17 00:00:00 2001 From: Vitus Ortner Date: Sat, 23 Feb 2019 17:42:56 +0100 Subject: [PATCH 7/7] WIP documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a9c68968..973e9ace 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ The Floor library provides a lightweight SQLite abstraction with automatic mapping between in-memory objects and database rows while still offering full control of the database with the use of SQL. -This package is still under active development and the API will likely change. +This package is still in an early phase and the API will likely change. ### Table of contents