Compare commits

...

31 Commits

Author SHA1 Message Date
ab7d277167 add note about transactions improvements 2021-03-05 20:42:30 +06:00
8308c1df4d update gradlewrapper up to 6.8.3 2021-03-05 19:12:26 +06:00
12c29f5180 Update packages_push.yml 2021-03-05 18:37:10 +06:00
2963098870 update publishing scripts 2021-03-05 16:43:50 +06:00
9f56b0a26d skip signing on publishing to packages 2021-03-05 16:34:16 +06:00
75851312fd remove old build yml 2021-03-05 16:24:43 +06:00
3a3be138a5 add packages publishing yml 2021-03-05 16:24:22 +06:00
fb7d1f18b0 update publication scripts 2021-03-05 16:21:36 +06:00
d1c6c7696a android database improvements 2021-03-05 16:15:21 +06:00
5f38d9635d update version of coroutines 2021-03-05 13:05:38 +06:00
8185ea87b1 start 0.4.29 2021-03-05 13:04:19 +06:00
98bd07d025 Merge pull request #50 from InsanusMokrassar/0.4.28
0.4.28
2021-03-02 01:09:48 +06:00
c502c70a21 should fix lint errors 2021-03-02 00:54:21 +06:00
d933dc532b add actions actor 2021-03-01 18:35:11 +06:00
42594f0656 update dependencies 2021-03-01 18:23:20 +06:00
4b83ca19c3 start 0.4.28 2021-03-01 18:21:34 +06:00
bab13f5e83 Update CHANGELOG.md 2021-02-26 15:35:15 +06:00
14c5f5a26c Merge pull request #48 from InsanusMokrassar/0.4.27
0.4.27
2021-02-23 13:09:04 +06:00
b26a4f24d4 fix in AbstractExposedWriteCRUDRepo 2021-02-23 12:51:13 +06:00
498ec673dc start 0.4.27 2021-02-23 12:50:55 +06:00
5c67ab6aec Merge pull request #47 from InsanusMokrassar/0.4.26
0.4.26
2021-02-21 21:36:09 +06:00
f78359b5d7 update serialization 2021-02-21 21:19:13 +06:00
dbce612cb2 start 0.4.26 2021-02-21 21:16:45 +06:00
4322ffdb0a Merge pull request #46 from InsanusMokrassar/0.4.25
0.4.25
2021-02-11 15:12:39 +06:00
123b848d74 update matrix test 2021-02-11 15:12:21 +06:00
b120fbd2b1 remove add and put column method in matrix row builder 2021-02-11 15:07:24 +06:00
d41c3c2de4 updates in matrix 2021-02-11 15:05:11 +06:00
a3cabd7a9e add matrix 2021-02-11 14:43:07 +06:00
3dde486126 start 0.4.25 2021-02-11 14:31:05 +06:00
5978122dda update scripts 2021-02-06 00:51:31 +06:00
4b4806ce34 Merge pull request #45 from InsanusMokrassar/0.4.24
0.4.24
2021-02-05 16:11:09 +06:00
27 changed files with 333 additions and 88 deletions

View File

@@ -1,16 +0,0 @@
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: ./gradlew build

24
.github/workflows/packages_push.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Publish package to GitHub Packages
on: [push]
jobs:
publishing:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Rewrite version
run: |
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
cat gradle.properties | sed -e "s/^version=\([0-9\.]*\)/version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
rm gradle.properties
mv gradle.properties.tmp gradle.properties
- name: Build
run: ./gradlew build
- name: Publish
run: ./gradlew --no-parallel publishAllPublicationsToGithubPackagesRepository -x signJsPublication -x signJvmPublication -x signKotlinMultiplatformPublication -x signMetadataPublication -x signAndroidDebugPublication -x signAndroidReleasePublication -x signKotlinMultiplatformPublication
env:
GITHUBPACKAGES_USER: ${{ github.actor }}
GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,5 +1,40 @@
# Changelog # Changelog
## 0.4.29
* `Versions`:
* `Coroutines`: `1.4.2` -> `1.4.3`
* `Repos`:
* `Common`
* `Android`:
* New `blockingReadableTransaction`/`blockingWritableTransaction`
* Android databases realizations now use blocking transactions where it is possible
* Several improvements in transactions work
## 0.4.28
* `Versions`:
* `Kotlin`: `1.4.30` -> `1.4.31`
* `Ktor`: `1.5.1` -> `1.5.2`
* `Coroutines`
* Add `createActionsActor`/`createSafeActionsActor` and `doWithSuspending`
## 0.4.27
* `Repos`
* `Exposed`
* Fix in `AbstractExposedWriteCRUDRepo`
## 0.4.26
* `Versions`:
* `Serialization`: `1.0.1` -> `1.1.0`
## 0.4.25
* `Matrix`:
* Subproject has been created
## 0.4.24 ## 0.4.24
* `Versions`: * `Versions`:

View File

@@ -0,0 +1,46 @@
package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlin.coroutines.*
interface ActorAction<T> {
suspend operator fun invoke(): T
}
/**
* Planned to use with [doWithSuspending]. Will execute incoming lambdas sequentially
*
* @see actor
*/
fun CoroutineScope.createActionsActor() = actor<suspend () -> Unit> {
it()
}
/**
* Planned to use with [doWithSuspending]. Will execute incoming lambdas sequentially
*
* @see safeActor
*/
inline fun CoroutineScope.createSafeActionsActor(
noinline onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler
) = safeActor<suspend () -> Unit>(Channel.UNLIMITED, onException) {
it()
}
/**
* Must be use with actor created by [createActionsActor] or [createSafeActionsActor]. Will send lambda which will
* execute [action] and return result.
*
* @see suspendCoroutine
* @see safely
*/
suspend fun <T> Channel<suspend () -> Unit>.doWithSuspending(
action: ActorAction<T>
) = suspendCoroutine<T> {
offer {
safely({ e -> it.resumeWithException(e) }) {
it.resume(action())
}
}
}

View File

@@ -6,12 +6,12 @@ kotlin.incremental.js=true
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
kotlin_version=1.4.30 kotlin_version=1.4.31
kotlin_coroutines_version=1.4.2 kotlin_coroutines_version=1.4.3
kotlin_serialisation_core_version=1.0.1 kotlin_serialisation_core_version=1.1.0
kotlin_exposed_version=0.29.1 kotlin_exposed_version=0.29.1
ktor_version=1.5.1 ktor_version=1.5.2
klockVersion=2.0.6 klockVersion=2.0.6
@@ -44,5 +44,5 @@ dokka_version=1.4.20
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.4.24 version=0.4.29
android_code_version=28 android_code_version=33

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

7
matrix/build.gradle Normal file
View File

@@ -0,0 +1,7 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -0,0 +1,3 @@
package dev.inmo.micro_utils.matrix
typealias Matrix<T> = List<Row<T>>

View File

@@ -0,0 +1,13 @@
package dev.inmo.micro_utils.matrix
class MatrixBuilder<T> {
private val mutMatrix: MutableList<List<T>> = ArrayList()
val matrix: Matrix<T>
get() = mutMatrix
fun row(t: List<T>) = mutMatrix.add(t)
operator fun List<T>.unaryPlus() = row(this)
}
fun <T> MatrixBuilder<T>.row(block: RowBuilder<T>.() -> Unit) = +RowBuilder<T>().also(block).row
fun <T> MatrixBuilder<T>.row(vararg elements: T) = +elements.toList()

View File

@@ -0,0 +1,17 @@
package dev.inmo.micro_utils.matrix
fun <T> matrix(block: MatrixBuilder<T>.() -> Unit): Matrix<T> {
return MatrixBuilder<T>().also(block).matrix
}
fun <T> flatMatrix(block: RowBuilder<T>.() -> Unit): Matrix<T> {
return MatrixBuilder<T>().apply {
row(block)
}.matrix
}
fun <T> flatMatrix(vararg elements: T): Matrix<T> {
return MatrixBuilder<T>().apply {
row { elements.forEach { +it } }
}.matrix
}

View File

@@ -0,0 +1,3 @@
package dev.inmo.micro_utils.matrix
typealias Row<T> = List<T>

View File

@@ -0,0 +1,14 @@
package dev.inmo.micro_utils.matrix
class RowBuilder<T> {
private val mutRow: MutableList<T> = ArrayList()
val row: Row<T>
get() = mutRow
fun column(t: T) = mutRow.add(t)
operator fun T.unaryPlus() = column(this)
}
fun <T> row(block: RowBuilder<T>.() -> Unit): List<T> = RowBuilder<T>().also(block).row
fun <T> RowBuilder<T>.columns(elements: List<T>) = elements.forEach(::column)
fun <T> RowBuilder<T>.columns(vararg elements: T) = elements.forEach(::column)

View File

@@ -0,0 +1,45 @@
package dev.inmo.micro_utils.matrix
import kotlin.test.Test
import kotlin.test.assertEquals
class SimpleTest {
@Test
fun simpleTest() {
val expected = listOf(
listOf(1, 2, 3),
listOf(4, 5, 6)
)
val fromMatrixWithVarargs = matrix<Int> {
row(1, 2, 3)
row(4, 5, 6)
}
val fromMatrixWithColumnsVarargs = matrix<Int> {
row {
columns(1, 2, 3)
}
row {
columns(4, 5, 6)
}
}
val fromMatrixWithSimpleAdd = matrix<Int> {
row {
column(1)
column(2)
column(3)
}
row {
column(4)
column(5)
column(6)
}
}
assertEquals(expected, fromMatrixWithVarargs)
assertEquals(expected, fromMatrixWithColumnsVarargs)
assertEquals(expected, fromMatrixWithSimpleAdd)
}
}

View File

@@ -0,0 +1 @@
<manifest package="dev.inmo.micro_utils.matrix"/>

View File

@@ -4,7 +4,9 @@ project.group = "$group"
apply from: "$publishGradlePath" apply from: "$publishGradlePath"
kotlin { kotlin {
jvm() jvm {
compilations.main.kotlinOptions.useIR = true
}
sourceSets { sourceSets {
commonMain { commonMain {

View File

@@ -4,7 +4,9 @@ project.group = "$group"
apply from: "$publishGradlePath" apply from: "$publishGradlePath"
kotlin { kotlin {
jvm() jvm {
compilations.main.kotlinOptions.useIR = true
}
js (BOTH) { js (BOTH) {
browser() browser()
nodejs() nodejs()

View File

@@ -1 +0,0 @@
{"bintrayConfig":{"repo":"MicroUtils","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/MicroUtils","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://git.inmo.dev/InsanusMokrassar/MicroUtils_mirror/src/master/LICENSE"}],"mavenConfig":{"name":"${project.name}","description":"","url":"https://git.inmo.dev/InsanusMokrassar/MicroUtils_mirror","vcsUrl":"ssh://git@git.inmo.dev:8322/InsanusMokrassar/MicroUtils_mirror.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"},{"id":"000Sanya","name":"Syrov Aleksandr","eMail":"000sanya.000sanya@gmail.com"}]}}

View File

@@ -10,13 +10,13 @@ publishing {
artifact javadocsJar artifact javadocsJar
pom { pom {
description = "" description = "It is set of projects with micro tools for avoiding of routines coding"
name = "${project.name}" name = "${project.name}"
url = "https://git.inmo.dev/InsanusMokrassar/MicroUtils_mirror" url = "https://github.com/InsanusMokrassar/MicroUtils/"
scm { scm {
developerConnection = "scm:git:[fetch=]ssh://git@git.inmo.dev:8322/InsanusMokrassar/MicroUtils_mirror.git[push=]ssh://git@git.inmo.dev:8322/InsanusMokrassar/MicroUtils_mirror.git" developerConnection = "scm:git:[fetch=]https://github.com/InsanusMokrassar/MicroUtils.git[push=]https://github.com/InsanusMokrassar/MicroUtils.git"
url = "ssh://git@git.inmo.dev:8322/InsanusMokrassar/MicroUtils_mirror.git" url = "https://github.com/InsanusMokrassar/MicroUtils.git"
} }
developers { developers {
@@ -40,27 +40,37 @@ publishing {
license { license {
name = "Apache Software License 2.0" name = "Apache Software License 2.0"
url = "https://git.inmo.dev/InsanusMokrassar/MicroUtils_mirror/src/master/LICENSE" url = "https://github.com/InsanusMokrassar/MicroUtils/blob/master/LICENSE"
} }
} }
} }
repositories { repositories {
maven { if ((project.hasProperty('GITHUBPACKAGES_USER') || System.getenv('GITHUBPACKAGES_USER') != null) && (project.hasProperty('GITHUBPACKAGES_PASSWORD') || System.getenv('GITHUBPACKAGES_PASSWORD') != null)) {
name = "bintray" maven {
url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/MicroUtils/${project.name}/;publish=1;override=1") name = "GithubPackages"
credentials { url = uri("https://maven.pkg.github.com/InsanusMokrassar/MicroUtils")
username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER') credentials {
password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY') username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
} }
} }
} }
} }
} }
signing { signing {
useGpgCmd() useGpgCmd()
publishing.publications.forEach { sign it } sign publishing.publications
} }

1
publish.kpsb Normal file
View File

@@ -0,0 +1 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/MicroUtils/blob/master/LICENSE"}],"mavenConfig":{"name":"${project.name}","description":"It is set of projects with micro tools for avoiding of routines coding","url":"https://github.com/InsanusMokrassar/MicroUtils/","vcsUrl":"https://github.com/InsanusMokrassar/MicroUtils.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"},{"id":"000Sanya","name":"Syrov Aleksandr","eMail":"000sanya.000sanya@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/MicroUtils"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}]}}

View File

@@ -26,20 +26,39 @@ fun SQLiteDatabase.createTable(
} }
} }
fun Cursor.getString(columnName: String) = getString( /**
getColumnIndex(columnName) * @throws IllegalArgumentException
*/
fun Cursor.getString(columnName: String): String = getString(
getColumnIndexOrThrow(columnName)
) )
fun Cursor.getLong(columnName: String) = getLong( /**
getColumnIndex(columnName) * @throws IllegalArgumentException
*/
fun Cursor.getShort(columnName: String): Short = getShort(
getColumnIndexOrThrow(columnName)
) )
fun Cursor.getInt(columnName: String) = getInt( /**
getColumnIndex(columnName) * @throws IllegalArgumentException
*/
fun Cursor.getLong(columnName: String): Long = getLong(
getColumnIndexOrThrow(columnName)
) )
fun Cursor.getDouble(columnName: String) = getDouble( /**
getColumnIndex(columnName) * @throws IllegalArgumentException
*/
fun Cursor.getInt(columnName: String): Int = getInt(
getColumnIndexOrThrow(columnName)
)
/**
* @throws IllegalArgumentException
*/
fun Cursor.getDouble(columnName: String): Double = getDouble(
getColumnIndexOrThrow(columnName)
) )
fun SQLiteDatabase.select( fun SQLiteDatabase.select(

View File

@@ -32,7 +32,9 @@ private object ContextsPool {
suspend fun <T> use(block: suspend (CoroutineContext) -> T): T = acquireContext().let { suspend fun <T> use(block: suspend (CoroutineContext) -> T): T = acquireContext().let {
try { try {
block(it) safely {
block(it)
}
} finally { } finally {
freeContext(it) freeContext(it)
} }
@@ -48,11 +50,12 @@ class TransactionContext(
} }
suspend fun <T> SQLiteDatabase.transaction(block: suspend SQLiteDatabase.() -> T): T { suspend fun <T> SQLiteDatabase.transaction(block: suspend SQLiteDatabase.() -> T): T {
return coroutineContext[TransactionContext] ?.let { coroutineContext[TransactionContext] ?.let {
withContext(it.databaseContext) { return withContext(it.databaseContext) {
block() block()
} }
} ?: ContextsPool.use { context -> }
return ContextsPool.use { context ->
withContext(TransactionContext(context) + context) { withContext(TransactionContext(context) + context) {
beginTransaction() beginTransaction()
safely( safely(
@@ -70,18 +73,18 @@ suspend fun <T> SQLiteDatabase.transaction(block: suspend SQLiteDatabase.() -> T
} }
} }
inline fun <T> SQLiteDatabase.inlineTransaction(block: SQLiteDatabase.() -> T): T { inline fun <T> SQLiteDatabase.inlineTransaction(crossinline block: SQLiteDatabase.() -> T): T {
return when { return when {
inTransaction() -> block() inTransaction() -> block()
else -> { else -> {
beginTransaction() beginTransaction()
try { try {
block().also { block().also { setTransactionSuccessful() }
setTransactionSuccessful()
}
} finally { } finally {
endTransaction() endTransaction()
} }
} }
} }
} }
fun <T> SQLiteDatabase.blockingTransaction(block: SQLiteDatabase.() -> T): T = inlineTransaction(block)

View File

@@ -31,6 +31,20 @@ class StandardSQLHelper(
suspend fun <T> readableTransaction(block: suspend SQLiteDatabase.() -> T): T = sqlOpenHelper.readableTransaction(block) suspend fun <T> readableTransaction(block: suspend SQLiteDatabase.() -> T): T = sqlOpenHelper.readableTransaction(block)
} }
fun <T> SQLiteOpenHelper.blockingWritableTransaction(block: SQLiteDatabase.() -> T): T {
return writableDatabase.blockingTransaction(block)
}
fun <T> SQLiteOpenHelper.blockingReadableTransaction(block: SQLiteDatabase.() -> T): T {
return readableDatabase.blockingTransaction(block)
}
fun <T> StandardSQLHelper.blockingWritableTransaction(block: SQLiteDatabase.() -> T): T {
return sqlOpenHelper.blockingWritableTransaction(block)
}
fun <T> StandardSQLHelper.blockingReadableTransaction(block: SQLiteDatabase.() -> T): T {
return sqlOpenHelper.blockingReadableTransaction(block)
}
suspend fun <T> SQLiteOpenHelper.writableTransaction(block: suspend SQLiteDatabase.() -> T): T { suspend fun <T> SQLiteOpenHelper.writableTransaction(block: suspend SQLiteDatabase.() -> T): T {
return writableDatabase.transaction(block) return writableDatabase.transaction(block)
} }

View File

@@ -20,7 +20,7 @@ abstract class AbstractAndroidCRUDRepo<ObjectType, IdType>(
it.count it.count
}.toLong() }.toLong()
override suspend fun contains(id: IdType): Boolean = helper.readableTransaction { override suspend fun contains(id: IdType): Boolean = helper.blockingReadableTransaction {
select( select(
tableName, tableName,
null, null,

View File

@@ -19,9 +19,10 @@ abstract class AbstractMutableAndroidCRUDRepo<ObjectType, IdType, InputValueType
protected abstract suspend fun InputValueType.asContentValues(id: IdType? = null): ContentValues protected abstract suspend fun InputValueType.asContentValues(id: IdType? = null): ContentValues
override suspend fun create(values: List<InputValueType>): List<ObjectType> { override suspend fun create(values: List<InputValueType>): List<ObjectType> {
val indexes = helper.writableTransaction { val valuesContentValues = values.map { it.asContentValues() }
values.map { val indexes = helper.blockingWritableTransaction {
insert(tableName, null, it.asContentValues()) valuesContentValues.map {
insert(tableName, null, it)
} }
} }
return helper.readableTransaction { return helper.readableTransaction {
@@ -47,7 +48,7 @@ abstract class AbstractMutableAndroidCRUDRepo<ObjectType, IdType, InputValueType
override suspend fun deleteById(ids: List<IdType>) { override suspend fun deleteById(ids: List<IdType>) {
val deleted = mutableListOf<IdType>() val deleted = mutableListOf<IdType>()
helper.writableTransaction { helper.blockingWritableTransaction {
ids.forEach { id -> ids.forEach { id ->
delete(tableName, "$idColumnName=?", arrayOf(id.asId)).also { delete(tableName, "$idColumnName=?", arrayOf(id.asId)).also {
if (it > 0) { if (it > 0) {
@@ -64,7 +65,7 @@ abstract class AbstractMutableAndroidCRUDRepo<ObjectType, IdType, InputValueType
override suspend fun update(id: IdType, value: InputValueType): ObjectType? { override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
val asContentValues = value.asContentValues(id) val asContentValues = value.asContentValues(id)
if (asContentValues.keySet().isNotEmpty()) { if (asContentValues.keySet().isNotEmpty()) {
helper.writableTransaction { helper.blockingWritableTransaction {
update( update(
tableName, tableName,
asContentValues, asContentValues,
@@ -79,11 +80,12 @@ abstract class AbstractMutableAndroidCRUDRepo<ObjectType, IdType, InputValueType
} }
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType> { override suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType> {
val contentValues = values.map { (id, value) -> id to value.asContentValues(id) }
helper.writableTransaction { helper.writableTransaction {
values.forEach { (id, value) -> contentValues.forEach { (id, contentValues) ->
update( update(
tableName, tableName,
value.asContentValues(id), contentValues,
"$idColumnName=?", "$idColumnName=?",
arrayOf(id.asId) arrayOf(id.asId)
) )
@@ -98,5 +100,5 @@ abstract class AbstractMutableAndroidCRUDRepo<ObjectType, IdType, InputValueType
} }
} }
override suspend fun count(): Long = helper.readableTransaction { select(tableName).use { it.count.toLong() } } override suspend fun count(): Long = helper.blockingReadableTransaction { select(tableName).use { it.count.toLong() } }
} }

View File

@@ -42,21 +42,19 @@ class OneToManyAndroidRepo<Key, Value>(
private fun String.asKey(): Key = internalSerialFormat.decodeFromString(keySerializer, this) private fun String.asKey(): Key = internalSerialFormat.decodeFromString(keySerializer, this)
init { init {
runBlocking(DatabaseCoroutineContext) { helper.blockingWritableTransaction {
helper.writableTransaction { createTable(
createTable( tableName,
tableName, internalId to internalIdType,
internalId to internalIdType, idColumnName to ColumnType.Text.NOT_NULLABLE,
idColumnName to ColumnType.Text.NOT_NULLABLE, valueColumnName to ColumnType.Text.NULLABLE
valueColumnName to ColumnType.Text.NULLABLE )
)
}
} }
} }
override suspend fun add(toAdd: Map<Key, List<Value>>) { override suspend fun add(toAdd: Map<Key, List<Value>>) {
val added = mutableListOf<Pair<Key, Value>>() val added = mutableListOf<Pair<Key, Value>>()
helper.writableTransaction { helper.blockingWritableTransaction {
toAdd.forEach { (k, values) -> toAdd.forEach { (k, values) ->
values.forEach { v -> values.forEach { v ->
insert( insert(
@@ -78,7 +76,7 @@ class OneToManyAndroidRepo<Key, Value>(
} }
override suspend fun clear(k: Key) { override suspend fun clear(k: Key) {
helper.writableTransaction { helper.blockingWritableTransaction {
delete(tableName, "$idColumnName=?", arrayOf(k.asId())) delete(tableName, "$idColumnName=?", arrayOf(k.asId()))
}.also { }.also {
if (it > 0) { if (it > 0) {
@@ -88,7 +86,7 @@ class OneToManyAndroidRepo<Key, Value>(
} }
override suspend fun set(toSet: Map<Key, List<Value>>) { override suspend fun set(toSet: Map<Key, List<Value>>) {
val (clearedKeys, inserted) = helper.writableTransaction { val (clearedKeys, inserted) = helper.blockingWritableTransaction {
toSet.mapNotNull { (k, _) -> toSet.mapNotNull { (k, _) ->
if (delete(tableName, "$idColumnName=?", arrayOf(k.asId())) > 0) { if (delete(tableName, "$idColumnName=?", arrayOf(k.asId())) > 0) {
k k
@@ -110,13 +108,13 @@ class OneToManyAndroidRepo<Key, Value>(
inserted.forEach { newPair -> _onNewValue.emit(newPair) } inserted.forEach { newPair -> _onNewValue.emit(newPair) }
} }
override suspend fun contains(k: Key): Boolean = helper.readableTransaction { override suspend fun contains(k: Key): Boolean = helper.blockingReadableTransaction {
select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.asId()), limit = FirstPagePagination(1).limitClause()).use { select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.asId()), limit = FirstPagePagination(1).limitClause()).use {
it.count > 0 it.count > 0
} }
} }
override suspend fun contains(k: Key, v: Value): Boolean = helper.readableTransaction { override suspend fun contains(k: Key, v: Value): Boolean = helper.blockingReadableTransaction {
select( select(
tableName, tableName,
selection = "$idColumnName=? AND $valueColumnName=?", selection = "$idColumnName=? AND $valueColumnName=?",
@@ -127,7 +125,7 @@ class OneToManyAndroidRepo<Key, Value>(
} }
} }
override suspend fun count(): Long =helper.readableTransaction { override suspend fun count(): Long =helper.blockingReadableTransaction {
select( select(
tableName tableName
).use { ).use {
@@ -135,7 +133,7 @@ class OneToManyAndroidRepo<Key, Value>(
} }
}.toLong() }.toLong()
override suspend fun count(k: Key): Long = helper.readableTransaction { override suspend fun count(k: Key): Long = helper.blockingReadableTransaction {
select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.asId()), limit = FirstPagePagination(1).limitClause()).use { select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.asId()), limit = FirstPagePagination(1).limitClause()).use {
it.count it.count
} }
@@ -147,7 +145,7 @@ class OneToManyAndroidRepo<Key, Value>(
reversed: Boolean reversed: Boolean
): PaginationResult<Value> = count(k).let { count -> ): PaginationResult<Value> = count(k).let { count ->
val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination } val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination }
helper.readableTransaction { helper.blockingReadableTransaction {
select( select(
tableName, tableName,
selection = "$idColumnName=?", selection = "$idColumnName=?",
@@ -173,7 +171,7 @@ class OneToManyAndroidRepo<Key, Value>(
reversed: Boolean reversed: Boolean
): PaginationResult<Key> = count().let { count -> ): PaginationResult<Key> = count().let { count ->
val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination } val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination }
helper.readableTransaction { helper.blockingReadableTransaction {
select( select(
tableName, tableName,
limit = resultPagination.limitClause() limit = resultPagination.limitClause()
@@ -198,7 +196,7 @@ class OneToManyAndroidRepo<Key, Value>(
reversed: Boolean reversed: Boolean
): PaginationResult<Key> = count().let { count -> ): PaginationResult<Key> = count().let { count ->
val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination } val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination }
helper.readableTransaction { helper.blockingReadableTransaction {
select( select(
tableName, tableName,
selection = "$valueColumnName=?", selection = "$valueColumnName=?",
@@ -220,7 +218,7 @@ class OneToManyAndroidRepo<Key, Value>(
} }
override suspend fun remove(toRemove: Map<Key, List<Value>>) { override suspend fun remove(toRemove: Map<Key, List<Value>>) {
helper.writableTransaction { helper.blockingWritableTransaction {
toRemove.flatMap { (k, vs) -> toRemove.flatMap { (k, vs) ->
vs.mapNotNullA { v -> vs.mapNotNullA { v ->
if (delete(tableName, "$idColumnName=? AND $valueColumnName=?", arrayOf(k.asId(), v.asValue())) > 0) { if (delete(tableName, "$idColumnName=? AND $valueColumnName=?", arrayOf(k.asId(), v.asValue())) > 0) {

View File

@@ -60,9 +60,11 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
} }
}.let { }.let {
if (it > 0) { if (it > 0) {
select { transaction(db = database) {
selectById(this, id) select {
}.limit(1).firstOrNull() ?.asObject selectById(this, id)
}.limit(1).firstOrNull() ?.asObject
}
} else { } else {
null null
} }

View File

@@ -2,6 +2,7 @@ rootProject.name='micro_utils'
String[] includes = [ String[] includes = [
":common", ":common",
":matrix",
":crypto", ":crypto",
":selector:common", ":selector:common",
":pagination:common", ":pagination:common",