Skip to content

Commit 961d344

Browse files
committed
chore: exoquery support
1 parent dc7cae6 commit 961d344

File tree

1 file changed

+112
-0
lines changed
  • backend/jvm/src/main/kotlin/dev/suresh/db

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package dev.suresh.db
2+
3+
import io.exoquery.*
4+
5+
@JvmInline value class Email(val value: String)
6+
7+
data class People(
8+
val id: Long,
9+
val name: String,
10+
val email: Email?,
11+
val age: Int,
12+
val addressId: Long?
13+
)
14+
15+
data class Address(
16+
val id: Long,
17+
val street: String,
18+
val city: String,
19+
val state: String?,
20+
val zipCode: String?,
21+
val country: String
22+
)
23+
24+
data class Robot(
25+
val id: Long,
26+
val name: String,
27+
)
28+
29+
typealias sql = capture
30+
31+
// Applicative capture
32+
val people = sql { Table<People>() }
33+
val address = sql { Table<Address>() }
34+
val robot = sql { Table<Robot>() }
35+
36+
// Both people (Applicative capture) and pQuery (Direct capture) are isomorphic.
37+
val pQuery =
38+
sql.select {
39+
val p = from(people)
40+
p
41+
}
42+
43+
val map = sql { people.map { it.name to it.age } }
44+
45+
val filter = sql { people.filter { it.age > 10 } }
46+
47+
// Correlated subqueries
48+
val subQueries = sql { people.filter { it.age > people.map { it.age }.avg() } }
49+
50+
// Position aggregators
51+
val aggregators = sql { people.map { count(it.name) to avg(it.age) } }
52+
53+
val distinct = sql { people.map { it.name to it.age }.distinct() }
54+
55+
val limitAndOffest = sql { people.drop(1).take(10) }
56+
57+
val union = sql {
58+
people.filter { it.name.startsWith("aaa") } union people.filter { it.name.startsWith("bbb") }
59+
}
60+
61+
data class CommonType(val id: Long, val name: String)
62+
63+
// Map to common type and union
64+
val commonTyep = sql {
65+
people.map { CommonType(it.id, it.name) } union robot.map { CommonType(it.id, it.name) }
66+
}
67+
68+
fun select() {
69+
val s =
70+
sql.select {
71+
val p = from(people)
72+
val a = join(address) { a -> a.id == p.addressId }
73+
where { p.age > 10 }
74+
groupBy(p.name, p.age)
75+
sortBy(p.name to Ord.Asc, p.age to Ord.Desc)
76+
p to a
77+
}
78+
println(s.buildFor.Postgres().value)
79+
}
80+
81+
fun insert(p: People) {
82+
val set = sql { insert<People> { set(name to "xxxx") } }
83+
84+
sql {
85+
insert<People> { setParams(p).excluding(id) }
86+
.returning {
87+
it.id
88+
// Output(it.id, it.name)
89+
}
90+
}
91+
}
92+
93+
fun upsert(p: People) {
94+
sql {
95+
insert<People> {
96+
setParams(p).onConflictUpdate(id) { excluding -> set(name to "name" + "-" + excluding.name) }
97+
// setParams(p).onConflictIgnore(id) - Do nothing
98+
}
99+
}
100+
}
101+
102+
fun update(p: People) {
103+
sql { update<People> { setParams(p) }.where { id == param(p.id) } }
104+
}
105+
106+
fun delete(p: People) {
107+
sql { delete<People>().where { id == param(p.id) } }
108+
}
109+
110+
fun batch(p: Sequence<People>) {
111+
sql.batch(p) { p -> insert<People> { setParams(p).excluding(id) } }
112+
}

0 commit comments

Comments
 (0)