Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Apply query DSL changes to writerside docs #1926

Merged
merged 1 commit into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ transaction {
withSuspendTransaction {
println("Transaction # ${this.id}") // Transaction # 2
// This select also will be executed on some thread from Default dispatcher using the same transaction as its parent
FooTable.select { FooTable.id eq 1 }.single()[FooTable.id]
FooTable.selectAll().where { FooTable.id eq 1 }.single()[FooTable.id]
}
}
}
Expand All @@ -40,7 +40,7 @@ transaction {
runBlocking {
val result = newSuspendedTransaction(Dispatchers.IO) {
println("Transaction # ${this.id}") // Transaction # 3
FooTable.select { FooTable.id eq 1 }.single()[FooTable.id] // This select will be executed on some thread from IO dispatcher
FooTable.selectAll().where { FooTable.id eq 1 }.single()[FooTable.id] // This select will be executed on some thread from IO dispatcher
}
println("Result: $result") // Result: 1
}
Expand All @@ -59,7 +59,7 @@ runBlocking {
val launchResult = suspendedTransactionAsync(Dispatchers.IO) {
FooTable.insert { it[id] = 2 }

FooTable.select { FooTable.id eq 2 }.singleOrNull()?.getOrNull(FooTable.id)
FooTable.selectAll().where { FooTable.id eq 2 }.singleOrNull()?.getOrNull(FooTable.id)
}

println("Async result: " + (launchResult.await() ?: -1)) // Async result: 2
Expand Down
10 changes: 5 additions & 5 deletions documentation-website/Writerside/topics/Data-Types.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ JSON path strings can be used to extract values (either as JSON or as a scalar v
```kotlin
val projectName = Team.project.extract<String>("name")
val languageIsKotlin = Team.project.extract<String>("language").lowerCase() eq "kotlin"
Team.slice(projectName).select { languageIsKotlin }.map { it[projectName] }
Team.select(projectName).where { languageIsKotlin }.map { it[projectName] }
```

<note>
Expand All @@ -158,21 +158,21 @@ used, the provided path arguments should be `.name` and `.language` respectively
The JSON functions `exists()` and `contains()` are currently supported as well:
```kotlin
val hasActiveStatus = Team.project.exists(".active")
val activeProjects = Team.select { hasActiveStatus }.count()
val activeProjects = Team.selectAll().where { hasActiveStatus }.count()

// Depending on the database, filter paths can be provided instead, as well as optional arguments
// PostgreSQL example
val mainId = "Main"
val hasMainProject = Team.project.exists(".name ? (@ == \$main)", optional = "{\"main\":\"$mainId\"}")
val mainProjects = Team.select { hasMainProject }.map { it[Team.groupId] }
val mainProjects = Team.selectAll().where { hasMainProject }.map { it[Team.groupId] }

val usesKotlin = Team.project.contains("{\"language\":\"Kotlin\"}")
val kotlinTeams = Team.select { usesKotlin }.count()
val kotlinTeams = Team.selectAll().where { usesKotlin }.count()

// Depending on the database, an optional path can be provided too
// MySQL example
val usesKotlin = Team.project.contains("\"Kotlin\"", ".language")
val kotlinTeams = Team.select { usesKotlin }.count()
val kotlinTeams = Team.selectAll().where { usesKotlin }.count()
```

### Json Arrays
Expand Down
12 changes: 6 additions & 6 deletions documentation-website/Writerside/topics/Deep-Dive-into-DAO.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ Let's imagine that you want to find all users who rated second SW film with more
First of all, we should write that query using Exposed DSL.
```kotlin
val query = Users.innerJoin(UserRatings).innerJoin(StarWarsFilm)
.slice(Users.columns)
.select {
.select(Users.columns)
.where {
StarWarsFilms.sequelId eq 2 and (UserRatings.value gt 5)
}.withDistinct()
```
Expand All @@ -277,8 +277,8 @@ See example by @PaulMuriithi [here](https://github.com/PaulMuriithi/ExposedDates
Imagine that you want to sort cities by how many users each city has. In order to do so, you can write a sub-query which counts users in each city and order by that number. Though in order to do so you'll have to convert `Query` to `Expression`. This can be done using `wrapAsExpression` function:
```kotlin
val expression = wrapAsExpression<Int>(Users
.slice(Users.id.count())
.select {
.select(Users.id.count())
.where {
Cities.id eq Users.cityId
})
val cities = Cities
Expand Down Expand Up @@ -309,8 +309,8 @@ class StarWarsFilm(id: EntityID<Int>) : IntEntity(id) {

companion object : IntEntityClass<StarWarsFilm>(StarWarsFilms) {
override fun searchQuery(op: Op<Boolean>): Query {
return super.searchQuery(op).adjustSlice {
slice(columns + StarWarsFilms.rank)
return super.searchQuery(op).adjustSelect {
select(columns + StarWarsFilms.rank).set
}
}
}
Expand Down
76 changes: 34 additions & 42 deletions documentation-website/Writerside/topics/Deep-Dive-into-DSL.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,29 +101,29 @@ val rowCount: Int = insertStatement.insertedCount
### Read

```kotlin
val query: Query = StarWarsFilms.select { StarWarsFilms.sequelId eq 8 }
val query: Query = StarWarsFilms.selectAll().where { StarWarsFilms.sequelId eq 8 }
```

`Query` inherit `Iterable` so it is possible to traverse it with map/foreach etc'. For example:

```kotlin
StarWarsFilms.select { StarWarsFilms.sequelId eq 8 }.forEach {
StarWarsFilms.selectAll().where { StarWarsFilms.sequelId eq 8 }.forEach {
println(it[StarWarsFilms.name])
}
```

There is `slice` function which allows you to select specific columns or/and expressions.
There is `select` function which allows you to select specific columns or/and expressions.

```kotlin
val filmAndDirector = StarWarsFilms.slice(StarWarsFilms.name, StarWarsFilms.director).selectAll().map {
val filmAndDirector = StarWarsFilms.select(StarWarsFilms.name, StarWarsFilms.director).map {
it[StarWarsFilms.name] to it[StarWarsFilms.director]
}
```

If you want to select only distinct value then use `withDistinct()` function:

```kotlin
val directors = StarWarsFilms.slice(StarWarsFilms.director).select { StarWarsFilms.sequelId less 5 }.withDistinct().map {
val directors = StarWarsFilms.select(StarWarsFilms.director).where { StarWarsFilms.sequelId less 5 }.withDistinct().map {
it[StarWarsFilms.director]
}
```
Expand Down Expand Up @@ -220,19 +220,19 @@ val condition = when {
Op.build { StarWarsFilms.sequelId eq sequelId }
else -> null
}
val query = condition?.let { StarWarsFilms.select(condition) } ?: StarWarsFilms.selectAll()
val query = condition?.let { StarWarsFilms.selectAll().where(condition) } ?: StarWarsFilms.selectAll()
```

or

```Kotlin
val query = when {
directorName!=null && sequelId!=null ->
StarWarsFilms.select { StarWarsFilms.director eq directorName and (StarWarsFilms.sequelId eq sequelId) }
StarWarsFilms.selectAll().where { StarWarsFilms.director eq directorName and (StarWarsFilms.sequelId eq sequelId) }
directorName!=null ->
StarWarsFilms.select { StarWarsFilms.director eq directorName }
StarWarsFilms.selectAll().where { StarWarsFilms.director eq directorName }
sequelId!=null ->
StarWarsFilms.select { StarWarsFilms.sequelId eq sequelId }
StarWarsFilms.selectAll().where { StarWarsFilms.sequelId eq sequelId }
else -> StarWarsFilms.selectAll()
}
```
Expand All @@ -251,35 +251,35 @@ sequelId?.let {
```

But what if we want to conditionally select from another table and join it only when a condition is true?
You have to use `adjustColumnSet` and `adjustSlice` functions (available since 0.8.1) which allows to extend and modify `join` and `slice` parts of a query (see kdoc
You have to use `adjustColumnSet` and `adjustSelect` functions, which allow to extend and modify `join` and `select` parts of a query (see kdoc
on that functions):

```Kotlin
actorName?.let {
query.adjustColumnSet { innerJoin(Actors, { StarWarsFilms.sequelId }, { Actors.sequelId }) }
.adjustSlice { slice(fields + Actors.columns) }
.adjustSelect { select(fields + Actors.columns).set }
.andWhere { Actors.name eq actorName }
}
```

### Check for a match in a pattern

```kotlin
StarWarsFilms.select { StarWarsFilms.name like "The %" }
StarWarsFilms.selectAll().where { StarWarsFilms.name like "The %" }
```

`notLike` is also available to check for expressions that do not match the provided pattern.

To perform a pattern match that supports regular expressions, use `regexp` instead:

```kotlin
StarWarsFilms.select { StarWarsFilms.name regexp "^The(\\s\\w+){2}\$" }
StarWarsFilms.selectAll().where { StarWarsFilms.name regexp "^The(\\s\\w+){2}\$" }
```

### Check for a match in a range

```kotlin
StarWarsFilms.select { StarWarsFilms.sequelId.between(4, 6) }
StarWarsFilms.selectAll().where { StarWarsFilms.sequelId.between(4, 6) }
```

The `between` operator returns `true` if the expression is between the lower and upper range values (inclusive).
Expand All @@ -288,14 +288,14 @@ Date and time values are also supported as arguments.
### Check for a match in a collection

```kotlin
StarWarsFilms.select { StarWarsFilms.sequelId inList listOf(6, 4) }
StarWarsFilms.selectAll().where { StarWarsFilms.sequelId inList listOf(6, 4) }
```

`inList` also accepts multiple expressions to check for equality, either as a `Pair` or a `Triple`:

```kotlin
val topRated = listOf(5 to "Empire Strikes Back", 4 to "A New Hope")
StarWarsFilms.select {
StarWarsFilms.selectAll().where {
StarWarsFilms.sequelId to StarWarsFilms.name inList topRated
}
```
Expand All @@ -307,7 +307,7 @@ StarWarsFilms.select {
`count()` is a method of `Query` that is used like in the example below:

```kotlin
val count = StarWarsFilms.select { StarWarsFilms.sequelId eq 8 }.count()
val count = StarWarsFilms.selectAll().where { StarWarsFilms.sequelId eq 8 }.count()
```

## Order-by
Expand All @@ -321,12 +321,11 @@ StarWarsFilms.selectAll().orderBy(StarWarsFilms.sequelId to SortOrder.ASC)

## Group-by

In group-by, define fields and their functions (such as `count`) by the `slice()` method.
In group-by, define fields and their functions (such as `count`) by the `select()` method.

```kotlin
StarWarsFilms
.slice(StarWarsFilms.sequelId.count(), StarWarsFilms.director)
.selectAll()
.select(StarWarsFilms.sequelId.count(), StarWarsFilms.director)
.groupBy(StarWarsFilms.director)
```

Expand All @@ -347,7 +346,7 @@ You can use limit function to prevent loading large data sets or use it for pagi

```kotlin
// Take 2 films after the first one.
StarWarsFilms.select { StarWarsFilms.sequelId eq Actors.sequelId }.limit(2, offset = 1)
StarWarsFilms.selectAll().where { StarWarsFilms.sequelId eq Actors.sequelId }.limit(2, offset = 1)
```

## Join
Expand Down Expand Up @@ -375,8 +374,7 @@ Join to count how many actors star in each movie:

```kotlin
Actors.join(StarWarsFilms, JoinType.INNER, onColumn = Actors.sequelId, otherColumn = StarWarsFilms.sequelId)
.slice(Actors.name.count(), StarWarsFilms.name)
.selectAll()
.select(Actors.name.count(), StarWarsFilms.name)
.groupBy(StarWarsFilms.name)
```

Expand All @@ -385,17 +383,15 @@ other types of join conditions).

```kotlin
Actors.join(StarWarsFilms, JoinType.INNER, additionalConstraint = { StarWarsFilms.sequelId eq Actors.sequelId })
.slice(Actors.name.count(), StarWarsFilms.name)
.selectAll()
.select(Actors.name.count(), StarWarsFilms.name)
.groupBy(StarWarsFilms.name)
```

When joining on a foreign key, the more concise `innerJoin` can be used:

```kotlin
(Actors innerJoin Roles)
.slice(Roles.characterName.count(), Actors.name)
.selectAll()
.select(Roles.characterName.count(), Actors.name)
.groupBy(Actors.name)
.toList()
```
Expand All @@ -404,8 +400,7 @@ This is equivalent to the following:

```kotlin
Actors.join(Roles, JoinType.INNER, onColumn = Actors.id, otherColumn = Roles.actorId)
.slice(Roles.characterName.count(), Actors.name)
.selectAll()
.select(Roles.characterName.count(), Actors.name)
.groupBy(Actors.name)
.toList()
```
Expand All @@ -417,16 +412,16 @@ Per the SQL specification, the queries must have the same number of columns, and
Subqueries may be combined when supported by the database.

```kotlin
val lucasDirectedQuery = StarWarsFilms.slice(StarWarsFilms.name).select { StarWarsFilms.director eq "George Lucas" }
val abramsDirectedQuery = StarWarsFilms.slice(StarWarsFilms.name).select { StarWarsFilms.director eq "J.J. Abrams" }
val lucasDirectedQuery = StarWarsFilms.select(StarWarsFilms.name).where { StarWarsFilms.director eq "George Lucas" }
val abramsDirectedQuery = StarWarsFilms.select(StarWarsFilms.name).where { StarWarsFilms.director eq "J.J. Abrams" }
val filmNames = lucasDirectedQuery.union(abramsDirectedQuery).map { it[StarWarsFilms.name] }
```

Only unique rows are returned by default. Duplicates may be returned using `.unionAll()`.

```kotlin
val lucasDirectedQuery = StarWarsFilms.slice(StarWarsFilms.name).select { StarWarsFilms.director eq "George Lucas" }
val originalTrilogyQuery = StarWarsFilms.slice(StarWarsFilms.name).select { StarWarsFilms.sequelId inList (3..5) }
val lucasDirectedQuery = StarWarsFilms.select(StarWarsFilms.name).where { StarWarsFilms.director eq "George Lucas" }
val originalTrilogyQuery = StarWarsFilms.select(StarWarsFilms.name).where { StarWarsFilms.sequelId inList (3..5) }
val filmNames = lucasDirectedQuery.unionAll(originalTrilogyQuery).map { it[StarWarsFilms.name] }
```

Expand All @@ -446,23 +441,20 @@ Also, aliases allow you to use the same table in a join multiple times:
val sequelTable = StarWarsFilms.alias("sql")
val originalAndSequelNames = StarWarsFilms
.innerJoin(sequelTable, { StarWarsFilms.sequelId }, { sequelTable[StarWarsFilms.id] })
.slice(StarWarsFilms.name, sequelTable[StarWarsFilms.name])
.selectAll()
.select(StarWarsFilms.name, sequelTable[StarWarsFilms.name])
.map { it[StarWarsFilms.name] to it[sequelTable[StarWarsFilms.name]] }
```

And they can be used when selecting from sub-queries:

```kotlin
val starWarsFilms = StarWarsFilms
.slice(StarWarsFilms.id, StarWarsFilms.name)
.selectAll()
.select(StarWarsFilms.id, StarWarsFilms.name)
.alias("swf")
val id = starWarsFilms[StarWarsFilms.id]
val name = starWarsFilms[StarWarsFilms.name]
starWarsFilms
.slice(id, name)
.selectAll()
.select(id, name)
.map { it[id] to it[name] }
```

Expand Down Expand Up @@ -538,7 +530,7 @@ val id = StarWarsFilms.insertAndGetId {
```

```Kotlin
val firstValue = StarWarsFilms.slice(nextVal).selectAll().single()[nextVal]
val firstValue = StarWarsFilms.select(nextVal).single()[nextVal]
```

## Batch Insert
Expand Down Expand Up @@ -594,15 +586,15 @@ If you want to use `INSERT INTO ... SELECT ` SQL clause try Exposed analog `Tabl

```kotlin
val substring = users.name.substring(1, 2)
cities.insert(users.slice(substring).selectAll().orderBy(users.id).limit(2))
cities.insert(users.select(substring).orderBy(users.id).limit(2))
```

By default it will try to insert into all non auto-increment `Table` columns in order they defined in Table instance. If you want to specify columns or change the
order, provide list of columns as second parameter:

```kotlin
val userCount = users.selectAll().count()
users.insert(users.slice(stringParam("Foo"), Random().castTo<String>(VarCharColumnType()).substring(1, 10)).selectAll(), columns = listOf(users.name, users.id))
users.insert(users.select(stringParam("Foo"), Random().castTo<String>(VarCharColumnType()).substring(1, 10)), columns = listOf(users.name, users.id))
```

## Insert Or Ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ A: Yes. See [[How to use Json and JsonB types|DataTypes#how-to-use-json-and-json

A:
```kotlin
val plainSQL = FooTable.select {}.prepareSQL(QueryBuilder(false))
val plainSQL = FooTable.selectAll().where {}.prepareSQL(QueryBuilder(false))
```
Use QueryBuiler with `false` - if you want to inline statement arguments, `true` - to see '?' in query.

Expand Down
Loading
Loading