Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.sum() get the error if all values of a group is zero #570

Closed
ditansu opened this issue Oct 7, 2018 · 1 comment
Closed

.sum() get the error if all values of a group is zero #570

ditansu opened this issue Oct 7, 2018 · 1 comment

Comments

@ditansu
Copy link

ditansu commented Oct 7, 2018

TL;DR

.sum() get error if all values of at a group is zero
[ ERROR ] PostgreSQLError.decode: Could not decode Int: 0x0000000000000000 (NUMERIC). (ErrorMiddleware.swift:26)

Explain:

  1. Models:
final class TestTable: PostgreSQLModel {
  var id: Int?
  var name: String
  var score: Intstruct TestRecord: Content {
  let name: String
  let score: Int
}
  1. Query
return  conn.select()
        .column(\TestTable.name)
        .column(.sum(\TestTable.score), as: "score")
        .from(TestTable.self)
        .groupBy(\TestTable.name)
        .orderBy(\TestTable.name)
        .all(decoding: TestRecord.self)
  1. Good result

    _ = try TestTable(name: "test1", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test1", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test3", score: 2).save(on: conn).wait()

    _ = try TestTable(name: "test1", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test1", score: 0).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 0).save(on: conn).wait()
    _ = try TestTable(name: "test3", score: 1).save(on: conn).wait()
  1. Error for any variant below:
    _ = try TestTable(name: "test1", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test1", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test3", score: 0).save(on: conn).wait()
.
    _ = try TestTable(name: "test1", score: 0).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test1", score: 0).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test3", score: 1).save(on: conn).wait()
.
    _ = try TestTable(name: "test1", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 0).save(on: conn).wait()
    _ = try TestTable(name: "test1", score: 1).save(on: conn).wait()
    _ = try TestTable(name: "test2", score: 0).save(on: conn).wait()
    _ = try TestTable(name: "test3", score: 1).save(on: conn).wait()
.
  1. Error message:
[psql] [2018-10-07 20:37:19 +0000] SELECT "TestTable"."name", SUM("TestTable"."score") AS "score" FROM "TestTable" GROUP BY "TestTable"."name" ORDER BY "TestTable"."name" ASC []
[ ERROR ] PostgreSQLError.decode: Could not decode Int: 0x0000000000000000 (NUMERIC). (ErrorMiddleware.swift:26)
[WARNING] [Async] [QueueHandler] Read triggered when input queue was empty, ignoring: close(PostgreSQL.PostgreSQLMessage.CloseResponse.statement(name: "ELECT 3")).
@ditansu
Copy link
Author

ditansu commented Oct 8, 2018

Update:

It seems the Fluent have a problem to work with PostgreSQL's numeric type when value is zero
The .sum() function upper type from int8 to numeric - because int8 + int8 not adjusted to int8 size. So, workaround is change type from Int8 to lower, for example to PostgreSQLDataType.int4 or .int2. In this case result will be int8 or int4, which no have problem with zero. Sure, if that is applicable to your situation.

workaround example

extension TestTable: Migration {
  public static func prepare(on connection: PostgreSQLConnection) -> Future<Void> {
    return PostgreSQLDatabase.create(self, on: connection) { builder in
      builder.field(for: \.id, isIdentifier: true)
      builder.field(for: \.name)
      builder.field(for: \.score, type: PostgreSQLDataType.int4)
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants