Browse Source

server: Remove the available field from the balances table

Due to a bug, maintaining this field consistent has been tricky,
now the field is dropped and we use an index over a function instead.
scalafmt-draft
Alexis Hernandez 7 years ago
parent
commit
a485037201
  1. 10
      server/app/com/xsn/explorer/data/anorm/dao/BalancePostgresDAO.scala
  2. 4
      server/app/com/xsn/explorer/data/anorm/dao/StatisticsPostgresDAO.scala
  3. 5
      server/app/com/xsn/explorer/models/fields/BalanceField.scala
  4. 20
      server/conf/evolutions/default/5.sql
  5. 15
      server/test/com/xsn/explorer/data/BalancePostgresDataHandlerSpec.scala

10
server/app/com/xsn/explorer/data/anorm/dao/BalancePostgresDAO.scala

@ -16,20 +16,18 @@ class BalancePostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderingSQ
SQL( SQL(
""" """
|INSERT INTO balances |INSERT INTO balances
| (address, received, spent, available) | (address, received, spent)
|VALUES |VALUES
| ({address}, {received}, {spent}, {available}) | ({address}, {received}, {spent})
|ON CONFLICT (address) DO UPDATE |ON CONFLICT (address) DO UPDATE
| SET received = balances.received + EXCLUDED.received, | SET received = balances.received + EXCLUDED.received,
| spent = balances.spent + EXCLUDED.spent, | spent = balances.spent + EXCLUDED.spent
| available = balances.available + EXCLUDED.available
|RETURNING address, received, spent |RETURNING address, received, spent
""".stripMargin """.stripMargin
).on( ).on(
'address -> balance.address.string, 'address -> balance.address.string,
'received -> balance.received, 'received -> balance.received,
'spent -> balance.spent, 'spent -> balance.spent,
'available -> balance.available
).as(parseBalance.singleOpt).flatten ).as(parseBalance.singleOpt).flatten
} }
@ -41,7 +39,7 @@ class BalancePostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderingSQ
val orderBy = fieldOrderingSQLInterpreter.toOrderByClause(ordering) val orderBy = fieldOrderingSQLInterpreter.toOrderByClause(ordering)
SQL( SQL(
s""" s"""
|SELECT address, received, spent, available |SELECT address, received, spent
|FROM balances |FROM balances
|WHERE address NOT IN ( |WHERE address NOT IN (
| SELECT address | SELECT address

4
server/app/com/xsn/explorer/data/anorm/dao/StatisticsPostgresDAO.scala

@ -12,9 +12,9 @@ class StatisticsPostgresDAO {
SQL( SQL(
""" """
|SELECT |SELECT
| (SELECT SUM(available) FROM balances) AS total_supply, | (SELECT SUM(received - spent) FROM balances) AS total_supply,
| ( | (
| SELECT SUM(available) FROM balances | SELECT SUM(received - spent) FROM balances
| WHERE address NOT IN (SELECT address FROM hidden_addresses) | WHERE address NOT IN (SELECT address FROM hidden_addresses)
| ) AS circulating_supply, | ) AS circulating_supply,
| (SELECT COUNT(*) FROM transactions) AS transactions, | (SELECT COUNT(*) FROM transactions) AS transactions,

5
server/app/com/xsn/explorer/models/fields/BalanceField.scala

@ -19,5 +19,8 @@ object BalanceField {
case _ => None case _ => None
} }
implicit val columnNameResolver: ColumnNameResolver[BalanceField] = (field) => field.string implicit val columnNameResolver: ColumnNameResolver[BalanceField] = (field) => field match {
case Available => s"(${Received.string} - ${Spent.string})"
case f => f.string
}
} }

20
server/conf/evolutions/default/5.sql

@ -0,0 +1,20 @@
# --- !Ups
DROP INDEX balances_available_index;
ALTER TABLE balances
DROP COLUMN available;
CREATE INDEX balances_available_index ON balances ((received - spent));
# --- !Downs
DROP INDEX balances_available_index;
-- in case this down is applied, the table needs to be rebuilt.
ALTER TABLE balances
ADD COLUMN available DECIMAL(30, 15) NOT NULL DEFAULT 0;
CREATE INDEX balances_available_index ON balances (available);

15
server/test/com/xsn/explorer/data/BalancePostgresDataHandlerSpec.scala

@ -25,21 +25,6 @@ class BalancePostgresDataHandlerSpec extends PostgresDataHandlerSpec {
result mustEqual Good(balance) result mustEqual Good(balance)
} }
"set the available amount" in {
val address = DataHelper.createAddress("Xbh5pJdBNm8J9PxnEmwVcuQKRmZZ7DkpcF")
val balance = Balance(address, received = BigDecimal(10), spent = BigDecimal(5))
val result = dataHandler.upsert(balance)
result mustEqual Good(balance)
database.withConnection { implicit conn =>
val available = _root_.anorm
.SQL(s"SELECT available FROM balances WHERE address = '${address.string}'")
.as(_root_.anorm.SqlParser.get[BigDecimal]("available").single)
available mustEqual balance.available
}
}
"update an existing balance" in { "update an existing balance" in {
val address = DataHelper.createAddress("XfAATXtkRgCdMTrj2fxHvLsKLLmqAjhEAt") val address = DataHelper.createAddress("XfAATXtkRgCdMTrj2fxHvLsKLLmqAjhEAt")
val initialBalance = Balance(address, received = BigDecimal(10), spent = BigDecimal(5)) val initialBalance = Balance(address, received = BigDecimal(10), spent = BigDecimal(5))

Loading…
Cancel
Save