Skip to content

Commit 552d145

Browse files
authored
Fix Sqldelight integration (#12)
* Fix Sqldelight integration * Disable compiler cache on linux * Implement custom postgres types * Remove useless test * Use build * Update CI.yml * Update CI.yml * Fix sqlite linking * Update CI.yml * Update CI.yml * Fix Statement index * Fix Statement index Co-authored-by: hfhbd <[email protected]>
1 parent d09b8ca commit 552d145

File tree

13 files changed

+412
-39
lines changed

13 files changed

+412
-39
lines changed

.github/workflows/CI.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ jobs:
3737
distribution: 'adopt'
3838
java-version: 11
3939
- run: ./gradlew assemble
40-
- run: ./gradlew allTests
40+
- run: ./gradlew build
4141
- uses: actions/upload-artifact@v3
42-
with:
43-
path: build/reports/tests
42+
with:
43+
path: |
44+
build/reports/tests
45+
testing/build/reports/tests
4446
if: failure()

build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugins {
77

88
repositories {
99
mavenCentral()
10+
maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
1011
}
1112

1213
kotlin {
@@ -39,7 +40,9 @@ kotlin {
3940
sourceSets {
4041
commonMain {
4142
dependencies {
42-
api("app.cash.sqldelight:runtime:2.0.0-alpha02")
43+
api("app.cash.sqldelight:runtime:2.0.0-SNAPSHOT")
44+
api("org.jetbrains.kotlinx:kotlinx-datetime:0.3.3")
45+
api("app.softwork:kotlinx-uuid-core:0.0.15")
4346
}
4447
}
4548
commonTest {

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ kotlin.code.style=official
22
kotlin.mpp.enableCInteropCommonization=true
33

44
kotlin.native.cacheKind.macosArm64=none
5+
kotlin.native.cacheKind.linuxX64=none

native-dialect/build.gradle.kts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
plugins {
2+
kotlin("jvm")
3+
id("com.github.johnrengelman.shadow") version "7.1.2"
4+
}
5+
6+
repositories {
7+
mavenCentral()
8+
maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
9+
maven(url = "https://www.jetbrains.com/intellij-repository/releases")
10+
maven(url = "https://cache-redirector.jetbrains.com/intellij-dependencies")
11+
}
12+
13+
dependencies {
14+
api("app.cash.sqldelight:postgresql-dialect:2.0.0-SNAPSHOT")
15+
16+
compileOnly("app.cash.sqldelight:dialect-api:2.0.0-SNAPSHOT")
17+
18+
val idea = "211.7628.21"
19+
compileOnly("com.jetbrains.intellij.platform:core-impl:$idea")
20+
compileOnly("com.jetbrains.intellij.platform:lang-impl:$idea")
21+
22+
testImplementation("com.jetbrains.intellij.platform:core-impl:$idea")
23+
testImplementation("com.jetbrains.intellij.platform:lang-impl:$idea")
24+
testImplementation(kotlin("test-junit"))
25+
}
26+
27+
configurations.all {
28+
exclude(group = "com.jetbrains.rd")
29+
exclude(group = "com.github.jetbrains", module = "jetCheck")
30+
exclude(group = "org.roaringbitmap")
31+
}
32+
33+
tasks.shadowJar {
34+
classifier = ""
35+
include("*.jar")
36+
include("app/cash/sqldelight/**")
37+
include("app/softwork/sqldelight/postgresdialect/**")
38+
include("META-INF/services/*")
39+
}
40+
41+
tasks.jar.configure {
42+
// Prevents shadowJar (with classifier = '') and this task from writing to the same path.
43+
enabled = false
44+
}
45+
46+
configurations {
47+
fun conf(it: Configuration) {
48+
it.outgoing.artifacts.removeIf { it.buildDependencies.getDependencies(null).contains(tasks.jar.get()) }
49+
it.outgoing.artifact(tasks.shadowJar)
50+
}
51+
apiElements.configure {
52+
conf(this)
53+
}
54+
runtimeElements.configure { conf(this) }
55+
}
56+
57+
artifacts {
58+
runtimeOnly(tasks.shadowJar)
59+
archives(tasks.shadowJar)
60+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package app.softwork.sqldelight.postgresdialect
2+
3+
import app.cash.sqldelight.dialect.api.*
4+
import app.cash.sqldelight.dialects.postgresql.*
5+
import app.cash.sqldelight.dialects.postgresql.grammar.psi.*
6+
import com.alecstrong.sql.psi.core.psi.*
7+
import com.squareup.kotlinpoet.*
8+
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
9+
10+
class PostgresNativeDialect : PostgreSqlDialect() {
11+
override val runtimeTypes = RuntimeTypes(
12+
driverType = ClassName("app.softwork.sqldelight.postgresdriver", "PostgresNativeDriver"),
13+
cursorType = ClassName("app.softwork.sqldelight.postgresdriver", "PostgresCursor"),
14+
preparedStatementType = ClassName("app.softwork.sqldelight.postgresdriver", "PostgresPreparedStatement")
15+
)
16+
17+
override fun typeResolver(parentResolver: TypeResolver): TypeResolver = PostgresNativeTypeResolver(parentResolver)
18+
19+
class PostgresNativeTypeResolver(parentResolver: TypeResolver) : PostgreSqlTypeResolver(parentResolver) {
20+
override fun definitionType(typeName: SqlTypeName): IntermediateType = with(typeName) {
21+
check(this is PostgreSqlTypeName)
22+
val type = IntermediateType(
23+
when {
24+
smallIntDataType != null -> PostgreSqlType.SMALL_INT
25+
intDataType != null -> PostgreSqlType.INTEGER
26+
bigIntDataType != null -> PostgreSqlType.BIG_INT
27+
approximateNumericDataType != null -> PrimitiveType.REAL
28+
stringDataType != null -> PrimitiveType.TEXT
29+
uuidDataType != null -> PostgreSqlType.UUID
30+
smallSerialDataType != null -> PostgreSqlType.SMALL_INT
31+
serialDataType != null -> PostgreSqlType.INTEGER
32+
bigSerialDataType != null -> PostgreSqlType.BIG_INT
33+
dateDataType != null -> {
34+
when (dateDataType!!.firstChild.text) {
35+
"DATE" -> PostgreSqlType.DATE
36+
//"TIME" -> PostgreSqlType.TIME
37+
"TIMESTAMP" -> if (dateDataType!!.node.getChildren(null)
38+
.any { it.text == "WITH" }
39+
) PostgreSqlType.TIMESTAMP_TIMEZONE else PostgreSqlType.TIMESTAMP
40+
"TIMESTAMPTZ" -> PostgreSqlType.TIMESTAMP_TIMEZONE
41+
"INTERVAL" -> PostgreSqlType.INTERVAL
42+
else -> throw IllegalArgumentException("Unknown date type ${dateDataType!!.text}")
43+
}
44+
}
45+
jsonDataType != null -> PrimitiveType.TEXT
46+
booleanDataType != null -> PrimitiveType.BOOLEAN
47+
blobDataType != null -> PrimitiveType.BLOB
48+
else -> throw IllegalArgumentException("Unknown kotlin type for sql type ${this.text}")
49+
}
50+
)
51+
if (node.getChildren(null).map { it.text }.takeLast(2) == listOf("[", "]")) {
52+
return IntermediateType(object : DialectType {
53+
override val javaType = Array::class.asTypeName().parameterizedBy(type.javaType)
54+
55+
override fun prepareStatementBinder(columnIndex: String, value: CodeBlock) =
56+
CodeBlock.of("bindArray($columnIndex, %L)\n", value)
57+
58+
override fun cursorGetter(columnIndex: Int, cursorName: String) =
59+
CodeBlock.of("$cursorName.getArray($columnIndex)")
60+
})
61+
}
62+
return type
63+
}
64+
}
65+
}
66+
67+
internal enum class PostgreSqlType(override val javaType: TypeName): DialectType {
68+
SMALL_INT(SHORT) {
69+
override fun decode(value: CodeBlock) = CodeBlock.of("%L.toShort()", value)
70+
71+
override fun encode(value: CodeBlock) = CodeBlock.of("%L.toLong()", value)
72+
},
73+
INTEGER(INT) {
74+
override fun decode(value: CodeBlock) = CodeBlock.of("%L.toInt()", value)
75+
76+
override fun encode(value: CodeBlock) = CodeBlock.of("%L.toLong()", value)
77+
},
78+
BIG_INT(LONG),
79+
DATE(ClassName("kotlinx.datetime", "LocalDate")),
80+
//TIME(kotlinx.datetime.LocalTime::class.asTypeName()),
81+
TIMESTAMP(ClassName("kotlinx.datetime", "LocalDateTime")),
82+
TIMESTAMP_TIMEZONE(ClassName("kotlinx.datetime", "Instant")),
83+
INTERVAL(ClassName("kotlin.time", "Duration")),
84+
UUID(ClassName("kotlinx.uuid", "UUID"));
85+
86+
override fun prepareStatementBinder(columnIndex: String, value: CodeBlock): CodeBlock {
87+
return CodeBlock.builder()
88+
.add(
89+
when (this) {
90+
SMALL_INT, INTEGER, BIG_INT -> "bindLong"
91+
DATE -> "bindDate"
92+
//TIME -> "bindTime"
93+
TIMESTAMP -> "bindLocalTimestamp"
94+
TIMESTAMP_TIMEZONE -> "bindTimestamp"
95+
INTERVAL -> "bindInterval"
96+
UUID -> "bindUUID"
97+
}
98+
)
99+
.add("($columnIndex, %L)\n", value)
100+
.build()
101+
}
102+
103+
override fun cursorGetter(columnIndex: Int, cursorName: String): CodeBlock {
104+
return CodeBlock.of(
105+
when (this) {
106+
SMALL_INT, INTEGER, BIG_INT -> "$cursorName.getLong($columnIndex)"
107+
DATE -> "$cursorName.getDate($columnIndex)"
108+
//TIME -> "$cursorName.getTime($columnIndex)"
109+
TIMESTAMP -> "$cursorName.getLocalTimestamp($columnIndex)"
110+
TIMESTAMP_TIMEZONE -> "$cursorName.getTimestamp($columnIndex)"
111+
INTERVAL -> "$cursorName.getInterval($columnIndex)"
112+
UUID -> "$cursorName.getUUID($columnIndex)"
113+
}
114+
)
115+
}
116+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
app.softwork.sqldelight.postgresdialect.PostgresNativeDialect

settings.gradle.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
pluginManagement {
2+
repositories {
3+
gradlePluginPortal()
4+
maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
5+
maven(url = "https://www.jetbrains.com/intellij-repository/releases")
6+
maven(url = "https://cache-redirector.jetbrains.com/intellij-dependencies")
7+
}
8+
}
19

210
rootProject.name = "SqlDelightNativePostgres"
311

12+
include(":native-dialect")
13+
include(":testing")

0 commit comments

Comments
 (0)