Skip to content

Commit

Permalink
Merge pull request #92 from qiaoyuang/main
Browse files Browse the repository at this point in the history
Fix the grammar of documents
  • Loading branch information
qiaoyuang authored May 8, 2024
2 parents b337337 + 3c24dfb commit 7702fbc
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 75 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fun sample() {
}
}
```
SQLlin is able to insert Kotlin objects into database directly, and could query Kotlin objects directly from database. The serialization
SQLlin is able to insert Kotlin objects into database directly, and could query Kotlin objects from database directly. The serialization
and deserialization ability based on [kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization).

SQLlin supports these platforms:
Expand Down
27 changes: 13 additions & 14 deletions sqllin-driver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,24 @@

## Design

Initially, we need a multiplatform available low-level Kotlin API to call SQLite. Because we think _sqllin-dsl_
should be platform independent. So, we need the _sqllin-driver_, and _sqllin-dsl_ based on it. Our goal is
Initially, we needed a multiplatform available low-level Kotlin APIs to call SQLite. Because we thought _sqllin-dsl_
should be platform-independent. So, we needed _sqllin-driver_, and _sqllin-dsl_ on top of it. Our goal was
writing the common APIs in Kotlin Multiplatform common source set and they have different implementations on
different platforms.

In Android, not many ways to choose from. If we use the Android Framework SQLite Java APIs, everything will be simple,
but defect is many SQLite parameters cannot take effect on systems below Android P. If we writing JNI code
On Android, there are no many ways to choose from. If we use Android Framework SQLite Java APIs, everything will be simple,
but defect is many SQLite parameters cannot take effect on systems below Android P. If we write JNI code
to call SQLite C functions by ourselves, above problem will be resolved, but this will lead to a bigger problem:
In systems above Android N, Google doesn't allow developers call system built-in SQLite C functions in NDK. If
On systems above Android N, Google doesn't allow developers call system built-in SQLite C functions in NDK. If
we firmly choose this plan, we have to compile the SQLite source code into _sqllin-driver_, this will complicate
our project. Finally, we still choose based on Android Framework Java API.

In Native platforms, things look different. We can call SQLite C API directly, this is a most intuitive plan.
The interoperability of Kotlin/Native with C is very perfect, but in Kotlin/Native you must use some APIs that
very difficult to understanding to interop with C, like: `memScoped`, `CPointer`, `CPointerVarOf`, `toKString`, etc..
So, at the beginning, I chose the [SQLiter](https://github.com/touchlab/SQLiter), that's a Kotlin/Native multiplatform
library. If I use it, I can put the Kotlin-C interop translate to Kotlin language-internal calls. It is very
convenient. [SQLiter](https://github.com/touchlab/SQLiter) also is the driver that
[SQLDelight](https://github.com/cashapp/sqldelight) to call SQLite C library on native platforms. It is not only
our project. Finally, we still choose to use Android Framework Java API.

On Native platforms, things look different. We can call SQLite C APIs directly, this is a most intuitive plan.
The interoperability of Kotlin/Native with C is perfect, but in Kotlin/Native you must use some APIs to interop with C
that very difficult to understand, like: `memScoped`, `CPointer`, `CPointerVarOf`, `toKString`, etc..
So, at the beginning, I chose the [SQLiter](https://github.com/touchlab/SQLiter), it is a Kotlin/Native multiplatform
library. If I use it, I can put the Kotlin-C interop translate to Kotlin language-internal calling. It is very
convenient. [SQLiter](https://github.com/touchlab/SQLiter) also is the driver of [SQLDelight](https://github.com/cashapp/sqldelight) calling SQLite C library on native platforms. It not only
supports iOS, but also supports all the operating systems of Apple, Linux(x64) and Windows(mingwX86, mingwX64).

But a few months later. I found using [SQLiter](https://github.com/touchlab/SQLiter) also has some disadvantages. For
Expand Down
32 changes: 16 additions & 16 deletions sqllin-dsl/doc/advanced-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

中文版请见[这里](advanced-query-cn.md)

We have learned basic query and using SQL functions in query condition. Let's learn some query’s advanced skills.
We have learned basic querying and using SQL functions in querying conditions. Let's learn some advanced skills of querying.

## Unions

The _UNION_ operator used for merge two _SELECT_ statements' results and these results must be of the same type.
The _UNION_ operator is used for merge two _SELECT_ statements' results and these results must be of the same type.

In SQL, _UNION_ operator between with the two _SELECT_ statements, but in SQLlin, we use a higher-order function to
In SQL, the _UNION_ operator between with the two _SELECT_ statements, but in SQLlin, we use a higher-order function to
implement _UNION_:

```kotlin
Expand All @@ -25,8 +25,8 @@ fun sample() {
}
```

You just need to write your _SELECT_ statements in `UNION {...}` block. There must be at least two _SELECT_ statements
inside the `UNION {...}` block, if not, you will get a `IllegalStateException` when runtime.
You just need to write your _SELECT_ statements in the `UNION {...}` block. There must be at least two _SELECT_ statements
inside the `UNION {...}` block, if not, you will get a `IllegalStateException` at runtime.

If you want to use _UNION_ and _UNION ALL_ interchangeably, just use `UNION {...}` or `UNION_ALL {...}` block nesting:

Expand Down Expand Up @@ -59,7 +59,7 @@ SELECT * FROM person WHERE name = "Tom"

## Subqueries

SQLlin doesn't yet support subqueries, we will develop as soon as possible.
SQLlin doesn't support subqueries yet, we will develop as soon as possible.

## Join

Expand Down Expand Up @@ -92,7 +92,7 @@ data class CrossJoinStudent(
)
```

The `Transcript` represents a other table. And the `Student` represents the join query results' type(so `Student`
The `Transcript` represents an other table. And the `Student` represents the join querying results' type (so `Student`
doesn't need to be annotated `@DBRow`), it owns all column names that belong to `Person` and `Transcript`.

### Cross Join
Expand All @@ -111,8 +111,8 @@ The `CROSS_JOIN` function receives one or multiple `Table`s as parameters. In no
depended on the `Table` that be generated by _sqllin-processor_, but _JOIN_ operator will change it to specific type. In above sample, `CROSS_JOIN` changes
the type to `CrossJoinStudent`.

Note, because of _CROSS JOIN_ owns feature in SQL. If the columns that be queried by _SELECT_ statement that with _CROSS JOIN_ clause include the same
name column in the two tables, this will causing the query to fail. Because of a class isn't allowed to have multiple properties those have same name, _sqllin-dsl_
Note, because _CROSS JOIN_ owns feature in SQL. If the columns that be queried by a _SELECT_ statement that with _CROSS JOIN_ clause include the same
name columns in the two tables, this will cause the querying to fail. Because a class isn't allowed to have multiple properties those have same names, _sqllin-dsl_
doesn't support the _CROSS JOIN_ with columns of the same name.

### Inner Join
Expand All @@ -130,15 +130,15 @@ fun joinSample() {
```

The `INNER_JOIN` is similar to `CROSS_JOIN`, the deference is `INNER_JOIN` need to connect a `USING` or `ON` clause. If a _INNER JOIN_ statement
without the `USING` or `ON` clause, it is incomplete, but your code still be compiled and will do nothing in runtime.
without the `USING` or `ON` clause, it is incomplete, but your code still be compiled and will do nothing at runtime.

The `NATURAL_INNER_JOIN` will produce a complete _SELECT_ statement(the same with `CROSS_JOIN`). So, you can't add `USING` or `ON` clause behind it, this is
The `NATURAL_INNER_JOIN` will produce a complete _SELECT_ statement (same with `CROSS_JOIN`). So, you can't add a `USING` or `ON` clause behind it, this is
guaranteed by Kotlin compiler.

Note, the behavior of `INNER_JOIN` clause with `ON` clause is same to `CROSS_JOIN`, you can't select the column that has same name in two tables.
Note, the behavior of a `INNER_JOIN` clause with a `ON` clause is same with `CROSS_JOIN`, you can't select a column that has same name in two tables.

The `INNER_JOIN` have an alias that named `JOIN`, and `NATURAL_INNER_JOIN` also have an alias that named `NATURAL_JOIN`. That's liked you can
bypass the `INNER` keyword in SQL's inner join query.
The `INNER_JOIN` have an alias that named `JOIN`, and `NATURAL_INNER_JOIN` also have an alias that named `NATURAL_JOIN`. This is just like you can
bypass a `INNER` keyword in SQL's inner join querying.


### Left Outer Join
Expand All @@ -155,8 +155,8 @@ fun joinSample() {
}
```

The `LEFT_OUTER_JOIN`'s usage is very similar to `INNER_JOIN`, the difference just is their API names.
The `LEFT_OUTER_JOIN`'s usage is very similar with `INNER_JOIN`, the difference just is their API names.

## Finally

You have learned all usage with SQLlin, enjoy it and stay concerned about SQLlin's update :)
You have learned all usages with SQLlin, enjoy it and stay Stay tuned for SQLlin's updates :)
12 changes: 6 additions & 6 deletions sqllin-dsl/doc/concurrency-safety.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ unpredictable consequences. So, the best way is when you want to operate your
database, create a `Database` object, and when you finish your operating, close it immediately.

But, that's very inconvenient, we always have to create a database connection and
close it frequently, that is a waste of resources. For example, if we are developing
an Android app, and in a single page(Activity/Fragment), we hope we can keep a
`Database` object, when we want to operate the database in background threads(or
close it frequently, this is a waste of resources. For example, if we are developing
an Android app, and in a single page (Activity/Fragment), we hope we can keep a
`Database` object, when we want to operate the database in background threads (or
coroutines), just use it, and, close it in certain lifecycle
functions(`onDestroy`, `onStop`, etc..).
functions (`onDestroy`, `onStop`, etc.).

In that time, we should make sure the concurrency safety that we sharing the `Database`
object between different threads(or coroutines). So, start with the version `1.2.2`, we can
At that time, we should make sure the concurrency safety that we share the `Database`
object between different threads (or coroutines). So, start with the version `1.2.2`, we can
use the new API `Database#suspendedScope` to replace the usage of `database {}`. For
example, if we have some old code:

Expand Down
22 changes: 11 additions & 11 deletions sqllin-dsl/doc/getting-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## Installation via Maven with Gradle

Add the _sqllin-dsl_, _sqllin-driver_ and _sqllin-processor_ dependencies into your `build.gradle.kts`:
Add the dependencies of _sqllin-dsl_, _sqllin-driver_ and _sqllin-processor_ into your `build.gradle.kts`:

```kotlin
plugins {
Expand Down Expand Up @@ -47,7 +47,7 @@ dependencies {
}
```

> Note: If you want to add dependiences of SQLlin into your Kotlin/Native exectable program project, sometimes you need to add the `linkerOpts`
> Note: If you want to add dependencies of SQLlin into your Kotlin/Native executable program projects, sometimes you need to add the `linkerOpts`
> of SQLite into your `build.gradle.kts` correctly. You can refer to [issue #48](https://github.com/ctripcorp/SQLlin/issues/48) to get more information.
## Creating the Database
Expand All @@ -61,7 +61,7 @@ val database = Database(name = "Person.db", path = getGlobalPath(), version = 1)
```

The `DatabasePath` is the second parameter `path`'s type, it is represented differently on different platforms.
In Android, you can get it through [`Context`](https://developer.android.com/reference/android/content/Context), and you can get it through string in native platforms.
On Android, you can get it through [`Context`](https://developer.android.com/reference/android/content/Context), and you can get it through string on native platforms.
For example, you can define a expect function in your common source set:

```kotlin
Expand All @@ -86,7 +86,7 @@ val applicationContext: Context
}
```

In your iOS source set(similar in other Apple platforms), you can implement it by:
In your iOS source set (similar with other Apple platforms), you can implement it by:

```kotlin
import com.ctrip.sqllin.driver.DatabasePath
Expand All @@ -100,7 +100,7 @@ actual fun getGlobalDatabasePath(): DatabasePath =

```

You can config more SQLite arguments when you creating the `Database` instance:
You can config more SQLite arguments when you create the `Database` instance:

```kotlin
import com.ctrip.sqllin.driver.DatabaseConfiguration
Expand All @@ -127,10 +127,10 @@ val database = Database(
```

Note, because of limitation by Android Framework, the `inMemory`, `busyTimeout`, `lookasideSlotSize`, `lookasideSlotCount`
only work on Android 9 and higher. And, because of [sqlite-jdbc](https://github.com/xerial/sqlite-jdbc)(SQLlin base on it on JVM) doesn't support
only work on Android 9 and higher. And, because [sqlite-jdbc](https://github.com/xerial/sqlite-jdbc)(SQLlin is based on it on JVM) doesn't support
`sqlite3_config()`, the `lookasideSlotSize` and `lookasideSlotCount` don't work on JVM target.

Now, the operations that change database structure have not supported by DSL yet. So, you need to write these SQL statements by string
Now, the operations that change database structure haven't been supported by DSL yet. So, you need to write these SQL statements by string
as in `create` and `upgrade` parameters.

Usually, you just need to create one `Database` instance in your component lifecycle. So, you need to close database manually when the lifecycle ended:
Expand All @@ -143,7 +143,7 @@ override fun onDestroy() {

## Defining Your database entity

In _sqllin-dsl_, you can insert and query objects directly. So, you need to use the correct way to define your data class. For example:
In _sqllin-dsl_, you can insert and query objects directly. So, you need to use the correct way to define your data classes. For example:

```kotlin
import com.ctrip.sqllin.dsl.annotation.DBRow
Expand All @@ -157,14 +157,14 @@ data class Person(
)
```

Your database entity's property names should same with the database table's column names. The database entity cannot have properties with names different from all
column names in the table. But the count of your database entity's properties can less than the count of columns.
Your database entities' property names should be same with the database table's column names. The database entities cannot have properties with names different from all
column names in the table. But the count of your database entities' properties can less than the count of columns.

The `@DBRow`'s param `tableName` represents the table name in Database, please ensure pass
the correct value. If you don't pass the parameter manually, _sqllin-processor_ will use the class
name as table name, for example, `Person`'s default table name is "Person".

In _sqllin-dsl_, objects serialization to SQL and deserialization from cursor depend on _kotlinx.serialization_. So, you also need to add the `@Serializable` onto your data class.
In _sqllin-dsl_, objects are serialized to SQL and deserialized from cursor depend on _kotlinx.serialization_. So, you also need to add the `@Serializable` onto your data classes.

## Next Step

Expand Down
Loading

0 comments on commit 7702fbc

Please sign in to comment.