`.max()` (and possibly other aggregation functions) throw an error on empty table for MySQL
Cellane opened this issue · 4 comments
This is mostly a re-posting of issue vapor/fluent#541, since it seems the issue is related to MySQL-specific parts of Fluent, not Fluent itself. Here’s a minimal repro case:
// Todo.swift
import FluentMySQL
import Vapor
final class Todo: MySQLModel {
var id: Int?
var name: String
var order: Int
init(_ name: String, _ order: Int) {
self.name = name
self.order = order
}
}
extension Todo: Migration {}
extension Todo: Content {}
extension Todo: Parameter {}
// TodoController.swift
import Vapor
final class TodoController {
func createHandler(
_ req: Request,
todoData: CreateTodoRequest
) throws -> Future<Todo> {
return Todo.query(on: req)
.max(\Todo.order)
.catchMap { _ in 0 }
.flatMap { maxOrder in
let todo = Todo(todoData.name, maxOrder + 1)
return todo.save(on: req)
}
}
}
struct CreateTodoRequest: Content {
let name: String
}
// routes.swift
import Vapor
public func routes(_ router: Router) throws {
let todoController = TodoController()
router.post(CreateTodoRequest.self, at: "todos", use: todoController.createHandler)
}
This code attempts to find maximum value of the order
field and set the value of newly created object to be one higher.
However, when sending a {"name": "Test"}
request to localhost:8080/todos
, everything goes well until code reaches the return todo.save(on: req)
line; at that point, crash is emitted from the MySQL/Connection/MySQLConnection.swift:82
file, along with this error message:
Assertion failed: Attempting to call `send(...)` again before previous invocation has completed.
Package versions: Vapor 3.0.6, Fluent 3.0.0-rc.4.0.2, FluentMySQL 3.0.0-rc.4.0.3, MySQL 3.0.0-rc.4.3. MySQL itself is Docker image tagged as mysql:5
.
Forgot to mention: this really seems to only happen on an empty table (or possibly a table where MAX(order)
would have no value to return?); in other words, if MAX(order)
returns a non-null value, the code works correctly.
@Cellane I suspect this is related to an issue fixed in MySQL 3.0.0 (just released). Can you run swift package update
and let me know if that resolves it?
@tanner0101 I’m afraid I’m still hitting the same issue. This time the line number is 81, but the code on the line is the same.
Vapor 3.0.6, Fluent 3.0.0, FluentMySQL 3.0.0, MySQL 3.0.0.
Could it be somehow related to vapor/database-kit#43, by the way? The crash reported in that issue seems to originate from the same line of code.
Fixed here: vapor/fluent#450