Skip to content

Commit f12d71f

Browse files
hfhbdAlec Strong
andauthored
Fix compiler error: missing listener with SELECT without tables (sqldelight#3469)
* Fix compiler error: missing listener with SELECT without tables * Use ExecutableQuery if the query does not listen to any tables Co-authored-by: hfhbd <hfhbd@users.noreply.github.com> Co-authored-by: Alec Strong <AlecStrong@users.noreply.github.com>
1 parent eae3c34 commit f12d71f

File tree

9 files changed

+86
-21
lines changed

9 files changed

+86
-21
lines changed

sqldelight-compiler/integration-tests/src/test/kotlin/com/example/PlayerQueries.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,28 +128,28 @@ public class PlayerQueries(
128128
)
129129
}
130130

131-
public fun <T : Any> selectNull(mapper: (expr: Void?) -> T): Query<T> = Query(106890351,
132-
emptyArray(), driver, "Player.sq", "selectNull", "SELECT NULL") { cursor ->
131+
public fun <T : Any> selectNull(mapper: (expr: Void?) -> T): ExecutableQuery<T> = Query(106890351,
132+
driver, "Player.sq", "selectNull", "SELECT NULL") { cursor ->
133133
mapper(
134134
null
135135
)
136136
}
137137

138-
public fun selectNull(): Query<SelectNull> = selectNull { expr ->
138+
public fun selectNull(): ExecutableQuery<SelectNull> = selectNull { expr ->
139139
SelectNull(
140140
expr
141141
)
142142
}
143143

144-
public fun <T : Any> selectStuff(mapper: (expr: Long, expr_: Long) -> T): Query<T> =
145-
Query(-976770036, emptyArray(), driver, "Player.sq", "selectStuff", "SELECT 1, 2") { cursor ->
144+
public fun <T : Any> selectStuff(mapper: (expr: Long, expr_: Long) -> T): ExecutableQuery<T> =
145+
Query(-976770036, driver, "Player.sq", "selectStuff", "SELECT 1, 2") { cursor ->
146146
mapper(
147147
cursor.getLong(0)!!,
148148
cursor.getLong(1)!!
149149
)
150150
}
151151

152-
public fun selectStuff(): Query<SelectStuff> = selectStuff { expr, expr_ ->
152+
public fun selectStuff(): ExecutableQuery<SelectStuff> = selectStuff { expr, expr_ ->
153153
SelectStuff(
154154
expr,
155155
expr_

sqldelight-compiler/integration-tests/src/test/kotlin/com/example/TeamQueries.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.example
22

3+
import app.cash.sqldelight.ExecutableQuery
34
import app.cash.sqldelight.Query
45
import app.cash.sqldelight.TransacterImpl
56
import app.cash.sqldelight.core.integration.Shoots
@@ -56,15 +57,15 @@ public class TeamQueries(
5657
)
5758
}
5859

59-
public fun <T : Any> selectStuff(mapper: (expr: Long, expr_: Long) -> T): Query<T> =
60-
Query(397134288, emptyArray(), driver, "Team.sq", "selectStuff", "SELECT 1, 2") { cursor ->
60+
public fun <T : Any> selectStuff(mapper: (expr: Long, expr_: Long) -> T): ExecutableQuery<T> =
61+
Query(397134288, driver, "Team.sq", "selectStuff", "SELECT 1, 2") { cursor ->
6162
mapper(
6263
cursor.getLong(0)!!,
6364
cursor.getLong(1)!!
6465
)
6566
}
6667

67-
public fun selectStuff(): Query<SelectStuff> = selectStuff { expr, expr_ ->
68+
public fun selectStuff(): ExecutableQuery<SelectStuff> = selectStuff { expr, expr_ ->
6869
SelectStuff(
6970
expr,
7071
expr_

sqldelight-compiler/src/main/kotlin/app/cash/sqldelight/core/compiler/SelectQueryGenerator.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,20 +229,21 @@ class SelectQueryGenerator(
229229
if (query.arguments.isEmpty()) {
230230
// No need for a custom query type, return an instance of Query:
231231
// return Query(statement, selectForId) { resultSet -> ... }
232-
if (query.tablesObserved != null) {
232+
val tablesObserved = query.tablesObserved
233+
if (tablesObserved.isNullOrEmpty()) {
233234
function.addCode(
234-
"return %T(${query.id}, %L, $DRIVER_NAME, %S, %S, %S)%L",
235+
"return %T(${query.id}, $DRIVER_NAME, %S, %S, %S)%L",
235236
QUERY_TYPE,
236-
queryKeys(query.tablesObserved!!),
237237
query.statement.containingFile.name,
238238
query.name,
239239
query.statement.rawSqlText(),
240240
mapperLambda.build(),
241241
)
242242
} else {
243243
function.addCode(
244-
"return %T(${query.id}, $DRIVER_NAME, %S, %S, %S)%L",
244+
"return %T(${query.id}, %L, $DRIVER_NAME, %S, %S, %S)%L",
245245
QUERY_TYPE,
246+
queryKeys(tablesObserved),
246247
query.statement.containingFile.name,
247248
query.name,
248249
query.statement.rawSqlText(),
@@ -265,16 +266,15 @@ class SelectQueryGenerator(
265266
}
266267

267268
/**
268-
* Either emptyArray() or arrayOf("table1", "table2")
269+
* Add the table listener array: arrayOf("table1", "table2")
269270
*/
270271
private fun queryKeys(tablesObserved: List<TableNameElement>): CodeBlock {
271-
return if (tablesObserved.isEmpty()) CodeBlock.of("emptyArray()")
272-
else tablesObserved.map { CodeBlock.of("\"${it.name}\"") }
272+
return tablesObserved.map { CodeBlock.of("\"${it.name}\"") }
273273
.joinToCode(", ", prefix = "arrayOf(", suffix = ")")
274274
}
275275

276276
private fun NamedQuery.supertype() =
277-
if (tablesObserved == null) EXECUTABLE_QUERY_TYPE
277+
if (tablesObserved.isNullOrEmpty()) EXECUTABLE_QUERY_TYPE
278278
else QUERY_TYPE
279279

280280
/**

sqldelight-compiler/src/test/kotlin/app/cash/sqldelight/core/queries/SelectQueryFunctionTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ class SelectQueryFunctionTest {
201201
val generator = SelectQueryGenerator(file.namedQueries.first())
202202
assertThat(generator.customResultTypeFunction().toString()).contains(
203203
"""
204-
|public fun selectValues(): app.cash.sqldelight.Query<kotlin.String>
204+
|public fun selectValues(): app.cash.sqldelight.ExecutableQuery<kotlin.String>
205205
""".trimMargin(),
206206
)
207207
}
@@ -482,7 +482,7 @@ class SelectQueryFunctionTest {
482482

483483
assertThat(generator.customResultTypeFunction().toString()).isEqualTo(
484484
"""
485-
|public fun <T : kotlin.Any> selectData(mapper: (expr: java.lang.Void?) -> T): app.cash.sqldelight.Query<T> = app.cash.sqldelight.Query(${query.id}, emptyArray(), driver, "Test.sq", "selectData", "SELECT NULL") { cursor ->
485+
|public fun <T : kotlin.Any> selectData(mapper: (expr: java.lang.Void?) -> T): app.cash.sqldelight.ExecutableQuery<T> = app.cash.sqldelight.Query(${query.id}, driver, "Test.sq", "selectData", "SELECT NULL") { cursor ->
486486
| mapper(
487487
| null
488488
| )
@@ -1573,7 +1573,7 @@ class SelectQueryFunctionTest {
15731573

15741574
assertThat(generator.customResultTypeFunction().toString()).isEqualTo(
15751575
"""
1576-
|public fun selectIf(): app.cash.sqldelight.Query<kotlin.String> = app.cash.sqldelight.Query(${query.id}, emptyArray(), driver, "Test.sq", "selectIf", "SELECT IF(1 = 1, 'yes', 'no')") { cursor ->
1576+
|public fun selectIf(): app.cash.sqldelight.ExecutableQuery<kotlin.String> = app.cash.sqldelight.Query(${query.id}, driver, "Test.sq", "selectIf", "SELECT IF(1 = 1, 'yes', 'no')") { cursor ->
15771577
| check(cursor is app.cash.sqldelight.driver.jdbc.JdbcCursor)
15781578
| cursor.getString(0)!!
15791579
|}
@@ -1790,7 +1790,7 @@ class SelectQueryFunctionTest {
17901790

17911791
assertThat(generator.customResultTypeFunction().toString()).isEqualTo(
17921792
"""
1793-
|public fun query(expr: kotlin.String): app.cash.sqldelight.Query<kotlin.String> = QueryQuery(expr) { cursor ->
1793+
|public fun query(expr: kotlin.String): app.cash.sqldelight.ExecutableQuery<kotlin.String> = QueryQuery(expr) { cursor ->
17941794
| cursor.getString(0)!!
17951795
|}
17961796
|

sqldelight-compiler/src/test/kotlin/app/cash/sqldelight/core/queries/SelectQueryTypeTest.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,33 @@ class SelectQueryTypeTest {
159159
)
160160
}
161161

162+
@Test fun `query type generates properly without from`() {
163+
val file = FixtureCompiler.parseSql(
164+
"""
165+
|selectWithoutFrom:
166+
|SELECT 42;
167+
|
168+
""".trimMargin(),
169+
tempFolder,
170+
)
171+
172+
val query = file.namedQueries.first()
173+
val generator = SelectQueryGenerator(query)
174+
175+
assertThat(generator.querySubtype().toString()).isEqualTo(
176+
"""
177+
|private inner class SelectWithoutFromQuery<out T : kotlin.Any>(
178+
| mapper: (app.cash.sqldelight.db.SqlCursor) -> T,
179+
|) : app.cash.sqldelight.ExecutableQuery<T>(mapper) {
180+
| public override fun <R> execute(mapper: (app.cash.sqldelight.db.SqlCursor) -> R): app.cash.sqldelight.db.QueryResult<R> = driver.executeQuery(${query.id}, ""${'"'}SELECT 42""${'"'}, mapper, 0)
181+
|
182+
| public override fun toString(): kotlin.String = "Test.sq:selectWithoutFrom"
183+
|}
184+
|
185+
""".trimMargin(),
186+
)
187+
}
188+
162189
@Test fun `bind arguments are ordered in generated type`() {
163190
val file = FixtureCompiler.parseSql(
164191
"""

sqldelight-gradle-plugin/src/test/kotlin/app/cash/sqldelight/integrations/IntegrationTest.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,13 @@ class IntegrationTest {
273273
val result = runner.build()
274274
assertThat(result.output).contains("BUILD SUCCESSFUL")
275275
}
276+
277+
@Test fun selectWithoutFromTest() {
278+
val runner = GradleRunner.create()
279+
.withCommonConfiguration(File("src/test/selectWithoutFrom"))
280+
.withArguments("clean", "assemble", "--stacktrace")
281+
282+
val result = runner.build()
283+
assertThat(result.output).contains("BUILD SUCCESSFUL")
284+
}
276285
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
buildscript {
2+
apply from: "${projectDir.absolutePath}/../buildscript.gradle"
3+
}
4+
5+
apply plugin: 'org.jetbrains.kotlin.jvm'
6+
apply plugin: 'app.cash.sqldelight'
7+
8+
sqldelight {
9+
MyDatabase {
10+
packageName = "com.sample"
11+
dialect("app.cash.sqldelight:postgresql-dialect:${app.cash.sqldelight.VersionKt.VERSION}")
12+
}
13+
}
14+
15+
repositories {
16+
maven {
17+
url "file://${projectDir.absolutePath}/../../../../build/localMaven"
18+
}
19+
mavenCentral()
20+
}
21+
22+
dependencies {
23+
implementation "app.cash.sqldelight:jdbc-driver:${app.cash.sqldelight.VersionKt.VERSION}"
24+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
apply from: "../settings.gradle"
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
select:
2+
SELECT AVG(42, ?);

0 commit comments

Comments
 (0)