Skip to content

Commit

Permalink
Limit Postgres MIN/MAX to an arity of one
Browse files Browse the repository at this point in the history
  • Loading branch information
eygraber committed Aug 15, 2023
1 parent 4b3602c commit dbc6c3f
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import app.cash.sqldelight.dialects.postgresql.grammar.psi.PostgreSqlExtensionEx
import app.cash.sqldelight.dialects.postgresql.grammar.psi.PostgreSqlInsertStmt
import app.cash.sqldelight.dialects.postgresql.grammar.psi.PostgreSqlTypeName
import app.cash.sqldelight.dialects.postgresql.grammar.psi.PostgreSqlUpdateStmtLimited
import com.alecstrong.sql.psi.core.SqlAnnotationHolder
import com.alecstrong.sql.psi.core.psi.SqlColumnExpr
import com.alecstrong.sql.psi.core.psi.SqlCreateTableStmt
import com.alecstrong.sql.psi.core.psi.SqlExpr
Expand Down Expand Up @@ -110,6 +111,21 @@ class PostgreSqlTypeResolver(private val parentResolver: TypeResolver) : TypeRes
else -> null
}

override fun SqlFunctionExpr.validateFunction(
annotationHolder: SqlAnnotationHolder,
) {
when (functionName.text.lowercase()) {
"max", "min" -> {
if (exprList.size != 1) {
annotationHolder.createErrorAnnotation(
this,
"${functionName.text} only takes one argument",
)
}
}
}
}

override fun queryWithResults(sqlStmt: SqlStmt): QueryWithResults? {
sqlStmt.insertStmt?.let { insert ->
check(insert is PostgreSqlInsertStmt)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE TABLE minMaxTable(
first INTEGER,
second INTEGER
);

SELECT MAX(first) FROM minMaxTable;
SELECT MIN(first) FROM minMaxTable;

-- error[col 7]: MAX only takes one argument
SELECT MAX(first, second) FROM minMaxTable;

-- error[col 7]: MIN only takes one argument
SELECT MIN(first, second) FROM minMaxTable;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package app.cash.sqldelight.dialect.api

import com.alecstrong.sql.psi.core.SqlAnnotationHolder
import com.alecstrong.sql.psi.core.psi.SqlExpr
import com.alecstrong.sql.psi.core.psi.SqlFunctionExpr
import com.alecstrong.sql.psi.core.psi.SqlStmt
Expand All @@ -23,6 +24,8 @@ interface TypeResolver {
*/
fun functionType(functionExpr: SqlFunctionExpr): IntermediateType?

fun SqlFunctionExpr.validateFunction(annotationHolder: SqlAnnotationHolder) {}

/**
* @return the dialect specific (or [PrimitiveType]) for a type name.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import com.intellij.lang.ASTNode

internal class FunctionExprMixin(node: ASTNode?) : SqlFunctionExprImpl(node) {
override fun annotate(annotationHolder: SqlAnnotationHolder) {
if (parent is SqlResultColumn &&
typeResolver != AnsiSqlTypeResolver &&
typeResolver.functionType(this) == null
) {
annotationHolder.createErrorAnnotation(this, "Unknown function ${functionName.text}")
if (parent is SqlResultColumn) {
if (typeResolver != AnsiSqlTypeResolver &&
typeResolver.functionType(this) == null
) {
annotationHolder.createErrorAnnotation(this, "Unknown function ${functionName.text}")
} else {
with(typeResolver) {
validateFunction(annotationHolder)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import app.cash.sqldelight.core.compiler.SelectQueryGenerator
import app.cash.sqldelight.core.dialects.blobType
import app.cash.sqldelight.core.dialects.textType
import app.cash.sqldelight.test.util.FixtureCompiler
import com.alecstrong.sql.psi.core.psi.SqlFunctionExpr
import com.google.common.truth.Truth.assertThat
import com.squareup.burst.BurstJUnit4
import com.squareup.kotlinpoet.DOUBLE
Expand Down Expand Up @@ -404,6 +405,8 @@ class ExpressionTest {
else -> LONG
}

val f = file.children.filterIsInstance<SqlFunctionExpr>()

val query = file.namedQueries.first()
assertThat(query.resultColumns.map { it.javaType }).containsExactly(
ByteArray::class.asClassName().copy(nullable = true),
Expand Down

0 comments on commit dbc6c3f

Please sign in to comment.