Massive clean-up of DB & conversion to long for timestamps

Collated all development changes to DB so now we build
initial DB structure directly with final layout.
i.e. no ALTER TABLE, etc.

Reordered HSQLDB 'CREATE TYPE' statements into alphabetical order
for easier maintainability.

Replaced TIMESTAMP WITH TIME ZONE with simple BIGINT ("EpochMillis").
Timezone conversion is now a presentation task, rather than having
pretty values in database.

Removed associated conversion methods, like toOffsetDateTime(),
fromOffsetDateTime() and getZonedTimestampMilli().

Renamed some DB columns to make them more obviously timestamps, like:
Names.registered is now Names.registered_when.

Removed IFNULL(balance, 0) from HSQLDBAccountRepository as balances
are never null, or actually never 0 either.

Added more tests to increase API call, and hence repository, coverage.

Removed unused "milestone block" from Transactions.
This commit is contained in:
catbref 2020-05-07 12:16:22 +01:00
parent 359a35931e
commit 3094ec3c26
21 changed files with 904 additions and 1014 deletions

View File

@ -1,8 +1,5 @@
package org.qortal.repository.hsqldb;
import static org.qortal.repository.hsqldb.HSQLDBRepository.getZonedTimestampMilli;
import static org.qortal.repository.hsqldb.HSQLDBRepository.toOffsetDateTime;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@ -25,7 +22,7 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public ATData fromATAddress(String atAddress) throws DataException {
String sql = "SELECT creator, creation, version, asset_id, code_bytes, code_hash, "
String sql = "SELECT creator, created_when, version, asset_id, code_bytes, code_hash, "
+ "is_sleeping, sleep_until_height, is_finished, had_fatal_error, "
+ "is_frozen, frozen_balance "
+ "FROM ATs "
@ -36,7 +33,7 @@ public class HSQLDBATRepository implements ATRepository {
return null;
byte[] creatorPublicKey = resultSet.getBytes(1);
long creation = getZonedTimestampMilli(resultSet, 2);
long created = resultSet.getLong(2);
int version = resultSet.getInt(3);
long assetId = resultSet.getLong(4);
byte[] codeBytes = resultSet.getBytes(5); // Actually BLOB
@ -55,7 +52,7 @@ public class HSQLDBATRepository implements ATRepository {
if (frozenBalance == 0 && resultSet.wasNull())
frozenBalance = null;
return new ATData(atAddress, creatorPublicKey, creation, version, assetId, codeBytes, codeHash,
return new ATData(atAddress, creatorPublicKey, created, version, assetId, codeBytes, codeHash,
isSleeping, sleepUntilHeight, isFinished, hadFatalError, isFrozen, frozenBalance);
} catch (SQLException e) {
throw new DataException("Unable to fetch AT from repository", e);
@ -73,12 +70,12 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public List<ATData> getAllExecutableATs() throws DataException {
String sql = "SELECT AT_address, creator, creation, version, asset_id, code_bytes, code_hash, "
String sql = "SELECT AT_address, creator, created_when, version, asset_id, code_bytes, code_hash, "
+ "is_sleeping, sleep_until_height, had_fatal_error, "
+ "is_frozen, frozen_balance "
+ "FROM ATs "
+ "WHERE is_finished = false "
+ "ORDER BY creation ASC";
+ "ORDER BY created_when ASC";
List<ATData> executableATs = new ArrayList<>();
@ -91,7 +88,7 @@ public class HSQLDBATRepository implements ATRepository {
do {
String atAddress = resultSet.getString(1);
byte[] creatorPublicKey = resultSet.getBytes(2);
long creation = getZonedTimestampMilli(resultSet, 3);
long created = resultSet.getLong(3);
int version = resultSet.getInt(4);
long assetId = resultSet.getLong(5);
byte[] codeBytes = resultSet.getBytes(6); // Actually BLOB
@ -109,7 +106,7 @@ public class HSQLDBATRepository implements ATRepository {
if (frozenBalance == 0 && resultSet.wasNull())
frozenBalance = null;
ATData atData = new ATData(atAddress, creatorPublicKey, creation, version, assetId, codeBytes, codeHash,
ATData atData = new ATData(atAddress, creatorPublicKey, created, version, assetId, codeBytes, codeHash,
isSleeping, sleepUntilHeight, isFinished, hadFatalError, isFrozen, frozenBalance);
executableATs.add(atData);
@ -124,7 +121,7 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public List<ATData> getATsByFunctionality(byte[] codeHash, Boolean isExecutable, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT AT_address, creator, creation, version, asset_id, code_bytes, ")
sql.append("SELECT AT_address, creator, created_when, version, asset_id, code_bytes, ")
.append("is_sleeping, sleep_until_height, is_finished, had_fatal_error, ")
.append("is_frozen, frozen_balance ")
.append("FROM ATs ")
@ -133,7 +130,7 @@ public class HSQLDBATRepository implements ATRepository {
if (isExecutable != null)
sql.append("AND is_finished = ").append(isExecutable ? "false" : "true");
sql.append(" ORDER BY creation ");
sql.append(" ORDER BY created_when ");
if (reverse != null && reverse)
sql.append("DESC");
@ -148,7 +145,7 @@ public class HSQLDBATRepository implements ATRepository {
do {
String atAddress = resultSet.getString(1);
byte[] creatorPublicKey = resultSet.getBytes(2);
long creation = getZonedTimestampMilli(resultSet, 3);
long created = resultSet.getLong(3);
int version = resultSet.getInt(4);
long assetId = resultSet.getLong(5);
byte[] codeBytes = resultSet.getBytes(6); // Actually BLOB
@ -167,7 +164,7 @@ public class HSQLDBATRepository implements ATRepository {
if (frozenBalance == 0 && resultSet.wasNull())
frozenBalance = null;
ATData atData = new ATData(atAddress, creatorPublicKey, creation, version, assetId, codeBytes, codeHash,
ATData atData = new ATData(atAddress, creatorPublicKey, created, version, assetId, codeBytes, codeHash,
isSleeping, sleepUntilHeight, isFinished, hadFatalError, isFrozen, frozenBalance);
matchingATs.add(atData);
@ -202,7 +199,7 @@ public class HSQLDBATRepository implements ATRepository {
public void save(ATData atData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("ATs");
saveHelper.bind("AT_address", atData.getATAddress()).bind("creator", atData.getCreatorPublicKey()).bind("creation", toOffsetDateTime(atData.getCreation()))
saveHelper.bind("AT_address", atData.getATAddress()).bind("creator", atData.getCreatorPublicKey()).bind("created_when", atData.getCreation())
.bind("version", atData.getVersion()).bind("asset_id", atData.getAssetId())
.bind("code_bytes", atData.getCodeBytes()).bind("code_hash", atData.getCodeHash())
.bind("is_sleeping", atData.getIsSleeping()).bind("sleep_until_height", atData.getSleepUntilHeight())
@ -230,7 +227,7 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public ATStateData getATStateAtHeight(String atAddress, int height) throws DataException {
String sql = "SELECT creation, state_data, state_hash, fees, is_initial "
String sql = "SELECT created_when, state_data, state_hash, fees, is_initial "
+ "FROM ATStates "
+ "WHERE AT_address = ? AND height = ? "
+ "LIMIT 1";
@ -239,13 +236,13 @@ public class HSQLDBATRepository implements ATRepository {
if (resultSet == null)
return null;
long creation = getZonedTimestampMilli(resultSet, 1);
long created = resultSet.getLong(1);
byte[] stateData = resultSet.getBytes(2); // Actually BLOB
byte[] stateHash = resultSet.getBytes(3);
long fees = resultSet.getLong(4);
boolean isInitial = resultSet.getBoolean(5);
return new ATStateData(atAddress, height, creation, stateData, stateHash, fees, isInitial);
return new ATStateData(atAddress, height, created, stateData, stateHash, fees, isInitial);
} catch (SQLException e) {
throw new DataException("Unable to fetch AT state from repository", e);
}
@ -253,7 +250,7 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public ATStateData getLatestATState(String atAddress) throws DataException {
String sql = "SELECT height, creation, state_data, state_hash, fees, is_initial "
String sql = "SELECT height, created_when, state_data, state_hash, fees, is_initial "
+ "FROM ATStates "
+ "WHERE AT_address = ? "
+ "ORDER BY height DESC "
@ -264,13 +261,13 @@ public class HSQLDBATRepository implements ATRepository {
return null;
int height = resultSet.getInt(1);
long creation = getZonedTimestampMilli(resultSet, 2);
long created = resultSet.getLong(2);
byte[] stateData = resultSet.getBytes(3); // Actually BLOB
byte[] stateHash = resultSet.getBytes(4);
long fees = resultSet.getLong(5);
boolean isInitial = resultSet.getBoolean(6);
return new ATStateData(atAddress, height, creation, stateData, stateHash, fees, isInitial);
return new ATStateData(atAddress, height, created, stateData, stateHash, fees, isInitial);
} catch (SQLException e) {
throw new DataException("Unable to fetch latest AT state from repository", e);
}
@ -281,7 +278,7 @@ public class HSQLDBATRepository implements ATRepository {
String sql = "SELECT AT_address, state_hash, fees, is_initial "
+ "FROM ATStates "
+ "WHERE height = ? "
+ "ORDER BY creation ASC";
+ "ORDER BY created_when ASC";
List<ATStateData> atStates = new ArrayList<>();
@ -315,7 +312,7 @@ public class HSQLDBATRepository implements ATRepository {
HSQLDBSaver saveHelper = new HSQLDBSaver("ATStates");
saveHelper.bind("AT_address", atStateData.getATAddress()).bind("height", atStateData.getHeight())
.bind("creation", toOffsetDateTime(atStateData.getCreation())).bind("state_data", atStateData.getStateData())
.bind("created_when", atStateData.getCreation()).bind("state_data", atStateData.getStateData())
.bind("state_hash", atStateData.getStateHash()).bind("fees", atStateData.getFees())
.bind("is_initial", atStateData.isInitial());

View File

@ -290,7 +290,7 @@ public class HSQLDBAccountRepository implements AccountRepository {
@Override
public AccountBalanceData getBalance(String address, long assetId) throws DataException {
String sql = "SELECT IFNULL(balance, 0) FROM AccountBalances WHERE account = ? AND asset_id = ? LIMIT 1";
String sql = "SELECT balance FROM AccountBalances WHERE account = ? AND asset_id = ? LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql, address, assetId)) {
if (resultSet == null)
@ -307,7 +307,8 @@ public class HSQLDBAccountRepository implements AccountRepository {
@Override
public List<AccountBalanceData> getAssetBalances(long assetId, Boolean excludeZero) throws DataException {
StringBuilder sql = new StringBuilder(1024);
sql.append("SELECT account, IFNULL(balance, 0) FROM AccountBalances WHERE asset_id = ?");
sql.append("SELECT account, balance FROM AccountBalances WHERE asset_id = ?");
if (excludeZero != null && excludeZero)
sql.append(" AND balance != 0");
@ -334,7 +335,8 @@ public class HSQLDBAccountRepository implements AccountRepository {
public List<AccountBalanceData> getAssetBalances(List<String> addresses, List<Long> assetIds, BalanceOrdering balanceOrdering, Boolean excludeZero,
Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(1024);
sql.append("SELECT account, asset_id, IFNULL(balance, 0), asset_name FROM ");
sql.append("SELECT account, asset_id, balance, asset_name FROM ");
final boolean haveAddresses = addresses != null && !addresses.isEmpty();
final boolean haveAssetIds = assetIds != null && !assetIds.isEmpty();

View File

@ -1,8 +1,5 @@
package org.qortal.repository.hsqldb;
import static org.qortal.repository.hsqldb.HSQLDBRepository.getZonedTimestampMilli;
import static org.qortal.repository.hsqldb.HSQLDBRepository.toOffsetDateTime;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@ -133,14 +130,14 @@ public class HSQLDBAssetRepository implements AssetRepository {
}
@Override
public List<Long> getRecentAssetIds(long start) throws DataException {
public List<Long> getRecentAssetIds(long startTimestamp) throws DataException {
String sql = "SELECT asset_id FROM IssueAssetTransactions JOIN Assets USING (asset_id) "
+ "JOIN Transactions USING (signature) "
+ "WHERE creation >= ?";
+ "WHERE created_when >= ?";
List<Long> assetIds = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql, HSQLDBRepository.toOffsetDateTime(start))) {
try (ResultSet resultSet = this.repository.checkedExecute(sql, startTimestamp)) {
if (resultSet == null)
return assetIds;
@ -199,7 +196,8 @@ public class HSQLDBAssetRepository implements AssetRepository {
@Override
public OrderData fromOrderId(byte[] orderId) throws DataException {
String sql = "SELECT creator, have_asset_id, want_asset_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled, HaveAsset.asset_name, WantAsset.asset_name "
String sql = "SELECT creator, have_asset_id, want_asset_id, amount, fulfilled, price, ordered_when, "
+ "is_closed, is_fulfilled, HaveAsset.asset_name, WantAsset.asset_name "
+ "FROM AssetOrders "
+ "JOIN Assets AS HaveAsset ON HaveAsset.asset_id = have_asset_id "
+ "JOIN Assets AS WantAsset ON WantAsset.asset_id = want_asset_id "
@ -215,13 +213,14 @@ public class HSQLDBAssetRepository implements AssetRepository {
long amount = resultSet.getLong(4);
long fulfilled = resultSet.getLong(5);
long price = resultSet.getLong(6);
long timestamp = getZonedTimestampMilli(resultSet, 7);
long timestamp = resultSet.getLong(7);
boolean isClosed = resultSet.getBoolean(8);
boolean isFulfilled = resultSet.getBoolean(9);
String haveAssetName = resultSet.getString(10);
String wantAssetName = resultSet.getString(11);
return new OrderData(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, fulfilled, price, timestamp, isClosed, isFulfilled, haveAssetName, wantAssetName);
return new OrderData(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, fulfilled, price,
timestamp, isClosed, isFulfilled, haveAssetName, wantAssetName);
} catch (SQLException e) {
throw new DataException("Unable to fetch asset order from repository", e);
}
@ -242,14 +241,14 @@ public class HSQLDBAssetRepository implements AssetRepository {
return orders;
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT creator, asset_order_id, amount, fulfilled, price, ordered " + "FROM AssetOrders "
sql.append("SELECT creator, asset_order_id, amount, fulfilled, price, ordered_when FROM AssetOrders "
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND NOT is_closed AND NOT is_fulfilled ");
sql.append("ORDER BY price");
if (reverse != null && reverse)
sql.append(" DESC");
sql.append(", ordered");
sql.append(", ordered_when");
if (reverse != null && reverse)
sql.append(" DESC");
@ -265,7 +264,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
long amount = resultSet.getLong(3);
long fulfilled = resultSet.getLong(4);
long price = resultSet.getLong(5);
long timestamp = getZonedTimestampMilli(resultSet, 6);
long timestamp = resultSet.getLong(6);
boolean isClosed = false;
boolean isFulfilled = false;
@ -285,7 +284,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
List<Object> bindParams = new ArrayList<>(3);
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT creator, asset_order_id, amount, fulfilled, price, ordered " + "FROM AssetOrders "
sql.append("SELECT creator, asset_order_id, amount, fulfilled, price, ordered_when FROM AssetOrders "
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND NOT is_closed AND NOT is_fulfilled ");
Collections.addAll(bindParams, haveAssetId, wantAssetId);
@ -305,7 +304,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
if (minimumPrice != null && haveAssetId < wantAssetId)
sql.append(" DESC");
sql.append(", ordered");
sql.append(", ordered_when");
List<OrderData> orders = new ArrayList<>();
@ -319,7 +318,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
long amount = resultSet.getLong(3);
long fulfilled = resultSet.getLong(4);
long price = resultSet.getLong(5);
long timestamp = getZonedTimestampMilli(resultSet, 6);
long timestamp = resultSet.getLong(6);
boolean isClosed = false;
boolean isFulfilled = false;
@ -350,7 +349,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
return orders;
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT price, SUM(amount - fulfilled), MAX(ordered) " + "FROM AssetOrders "
sql.append("SELECT price, SUM(amount - fulfilled), MAX(ordered_when) FROM AssetOrders "
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND NOT is_closed AND NOT is_fulfilled "
+ "GROUP BY price ");
@ -367,7 +366,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
do {
long price = resultSet.getLong(1);
long totalUnfulfilled = resultSet.getLong(2);
long timestamp = resultSet.getTimestamp(3).getTime();
long timestamp = resultSet.getLong(3);
OrderData order = new OrderData(null, null, haveAssetId, wantAssetId, totalUnfulfilled, 0L,
price, timestamp, false, false, haveAssetData.getName(), wantAssetData.getName());
@ -384,7 +383,8 @@ public class HSQLDBAssetRepository implements AssetRepository {
public List<OrderData> getAccountsOrders(byte[] publicKey, Boolean optIsClosed, Boolean optIsFulfilled,
Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(1024);
sql.append("SELECT asset_order_id, have_asset_id, want_asset_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled, HaveAsset.asset_name, WantAsset.asset_name "
sql.append("SELECT asset_order_id, have_asset_id, want_asset_id, amount, fulfilled, price, ordered_when, "
+ "is_closed, is_fulfilled, HaveAsset.asset_name, WantAsset.asset_name "
+ "FROM AssetOrders "
+ "JOIN Assets AS HaveAsset ON HaveAsset.asset_id = have_asset_id "
+ "JOIN Assets AS WantAsset ON WantAsset.asset_id = want_asset_id "
@ -400,7 +400,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
sql.append(optIsFulfilled ? "TRUE" : "FALSE");
}
sql.append(" ORDER BY ordered");
sql.append(" ORDER BY ordered_when");
if (reverse != null && reverse)
sql.append(" DESC");
@ -419,7 +419,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
long amount = resultSet.getLong(4);
long fulfilled = resultSet.getLong(5);
long price = resultSet.getLong(6);
long timestamp = getZonedTimestampMilli(resultSet, 7);
long timestamp = resultSet.getLong(7);
boolean isClosed = resultSet.getBoolean(8);
boolean isFulfilled = resultSet.getBoolean(9);
String haveAssetName = resultSet.getString(10);
@ -451,7 +451,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
return orders;
StringBuilder sql = new StringBuilder(1024);
sql.append("SELECT asset_order_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled "
sql.append("SELECT asset_order_id, amount, fulfilled, price, ordered_when, is_closed, is_fulfilled "
+ "FROM AssetOrders "
+ "WHERE creator = ? AND have_asset_id = ? AND want_asset_id = ?");
@ -465,7 +465,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
sql.append(optIsFulfilled ? "TRUE" : "FALSE");
}
sql.append(" ORDER BY ordered");
sql.append(" ORDER BY ordered_when");
if (reverse != null && reverse)
sql.append(" DESC");
@ -480,7 +480,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
long amount = resultSet.getLong(2);
long fulfilled = resultSet.getLong(3);
long price = resultSet.getLong(4);
long timestamp = getZonedTimestampMilli(resultSet, 5);
long timestamp = resultSet.getLong(5);
boolean isClosed = resultSet.getBoolean(6);
boolean isFulfilled = resultSet.getBoolean(7);
@ -502,7 +502,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
saveHelper.bind("asset_order_id", orderData.getOrderId()).bind("creator", orderData.getCreatorPublicKey())
.bind("have_asset_id", orderData.getHaveAssetId()).bind("want_asset_id", orderData.getWantAssetId())
.bind("amount", orderData.getAmount()).bind("fulfilled", orderData.getFulfilled())
.bind("price", orderData.getPrice()).bind("ordered", toOffsetDateTime(orderData.getTimestamp()))
.bind("price", orderData.getPrice()).bind("ordered_when", orderData.getTimestamp())
.bind("is_closed", orderData.getIsClosed()).bind("is_fulfilled", orderData.getIsFulfilled());
try {
@ -538,11 +538,11 @@ public class HSQLDBAssetRepository implements AssetRepository {
return trades;
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT initiating_order_id, target_order_id, target_amount, initiator_amount, initiator_saving, traded "
sql.append("SELECT initiating_order_id, target_order_id, target_amount, initiator_amount, initiator_saving, traded_when "
+ "FROM AssetOrders JOIN AssetTrades ON initiating_order_id = asset_order_id "
+ "WHERE have_asset_id = ? AND want_asset_id = ? ");
sql.append("ORDER BY traded");
sql.append("ORDER BY traded_when");
if (reverse != null && reverse)
sql.append(" DESC");
@ -558,7 +558,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
long targetAmount = resultSet.getLong(3);
long initiatorAmount = resultSet.getLong(4);
long initiatorSaving = resultSet.getLong(5);
long timestamp = getZonedTimestampMilli(resultSet, 6);
long timestamp = resultSet.getLong(6);
TradeData trade = new TradeData(initiatingOrderId, targetOrderId, targetAmount, initiatorAmount, initiatorSaving,
timestamp, haveAssetId, haveAssetData.getName(), wantAssetId, wantAssetData.getName());
@ -615,18 +615,18 @@ public class HSQLDBAssetRepository implements AssetRepository {
tradedAssetsSubquery.append(" GROUP BY have_asset_id, want_asset_id");
// Find recent trades using "TradedAssets" assetID pairs
String recentTradesSubquery = "SELECT AssetTrades.target_amount, AssetTrades.initiator_amount, AssetTrades.traded "
String recentTradesSubquery = "SELECT AssetTrades.target_amount, AssetTrades.initiator_amount, AssetTrades.traded_when "
+ "FROM AssetOrders JOIN AssetTrades ON initiating_order_id = asset_order_id "
+ "WHERE AssetOrders.have_asset_id = TradedAssets.have_asset_id AND AssetOrders.want_asset_id = TradedAssets.want_asset_id "
+ "ORDER BY traded DESC LIMIT 2";
+ "ORDER BY traded_when DESC LIMIT 2";
// Put it all together
StringBuilder sql = new StringBuilder(4096);
sql.append("SELECT have_asset_id, want_asset_id, RecentTrades.target_amount, RecentTrades.initiator_amount, RecentTrades.traded FROM (");
sql.append("SELECT have_asset_id, want_asset_id, RecentTrades.target_amount, RecentTrades.initiator_amount, RecentTrades.traded_when FROM (");
sql.append(tradedAssetsSubquery);
sql.append(") AS TradedAssets, LATERAL (");
sql.append(recentTradesSubquery);
sql.append(") AS RecentTrades (target_amount, initiator_amount, traded) ORDER BY have_asset_id");
sql.append(") AS RecentTrades (target_amount, initiator_amount, traded_when) ORDER BY have_asset_id");
if (reverse != null && reverse)
sql.append(" DESC");
@ -634,7 +634,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
if (reverse != null && reverse)
sql.append(" DESC");
sql.append(", RecentTrades.traded DESC ");
sql.append(", RecentTrades.traded_when DESC ");
HSQLDBRepository.limitOffsetSql(sql, limit, offset);
@ -649,7 +649,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
long wantAssetId = resultSet.getLong(2);
long otherAmount = resultSet.getLong(3);
long amount = resultSet.getLong(4);
long timestamp = getZonedTimestampMilli(resultSet, 5);
long timestamp = resultSet.getLong(5);
RecentTradeData recentTrade = new RecentTradeData(haveAssetId, wantAssetId, otherAmount, amount,
timestamp);
@ -665,7 +665,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
@Override
public List<TradeData> getOrdersTrades(byte[] orderId, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT initiating_order_id, target_order_id, target_amount, initiator_amount, initiator_saving, traded, "
sql.append("SELECT initiating_order_id, target_order_id, target_amount, initiator_amount, initiator_saving, traded_when, "
+ "have_asset_id, HaveAsset.asset_name, want_asset_id, WantAsset.asset_name "
+ "FROM AssetTrades "
+ "JOIN AssetOrders ON asset_order_id = initiating_order_id "
@ -673,7 +673,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
+ "JOIN Assets AS WantAsset ON WantAsset.asset_id = want_asset_id "
+ "WHERE ? IN (initiating_order_id, target_order_id) ");
sql.append("ORDER BY traded");
sql.append("ORDER BY traded_when");
if (reverse != null && reverse)
sql.append(" DESC");
@ -691,7 +691,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
long targetAmount = resultSet.getLong(3);
long initiatorAmount = resultSet.getLong(4);
long initiatorSaving = resultSet.getLong(5);
long timestamp = getZonedTimestampMilli(resultSet, 6);
long timestamp = resultSet.getLong(6);
long haveAssetId = resultSet.getLong(7);
String haveAssetName = resultSet.getString(8);
@ -715,7 +715,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
saveHelper.bind("initiating_order_id", tradeData.getInitiator()).bind("target_order_id", tradeData.getTarget())
.bind("target_amount", tradeData.getTargetAmount()).bind("initiator_amount", tradeData.getInitiatorAmount())
.bind("initiator_saving", tradeData.getInitiatorSaving()).bind("traded", toOffsetDateTime(tradeData.getTimestamp()));
.bind("initiator_saving", tradeData.getInitiatorSaving()).bind("traded_when", tradeData.getTimestamp());
try {
saveHelper.execute(this.repository);

View File

@ -1,8 +1,5 @@
package org.qortal.repository.hsqldb;
import static org.qortal.repository.hsqldb.HSQLDBRepository.getZonedTimestampMilli;
import static org.qortal.repository.hsqldb.HSQLDBRepository.toOffsetDateTime;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@ -21,7 +18,7 @@ import org.qortal.repository.TransactionRepository;
public class HSQLDBBlockRepository implements BlockRepository {
private static final String BLOCK_DB_COLUMNS = "version, reference, transaction_count, total_fees, "
+ "transactions_signature, height, minted, minter, minter_signature, "
+ "transactions_signature, height, minted_when, minter, minter_signature, "
+ "AT_count, AT_fees, online_accounts, online_accounts_count, online_accounts_timestamp, online_accounts_signatures";
protected HSQLDBRepository repository;
@ -41,14 +38,18 @@ public class HSQLDBBlockRepository implements BlockRepository {
long totalFees = resultSet.getLong(4);
byte[] transactionsSignature = resultSet.getBytes(5);
int height = resultSet.getInt(6);
long timestamp = getZonedTimestampMilli(resultSet, 7);
long timestamp = resultSet.getLong(7);
byte[] minterPublicKey = resultSet.getBytes(8);
byte[] minterSignature = resultSet.getBytes(9);
int atCount = resultSet.getInt(10);
long atFees = resultSet.getLong(11);
byte[] encodedOnlineAccounts = resultSet.getBytes(12);
int onlineAccountsCount = resultSet.getInt(13);
Long onlineAccountsTimestamp = getZonedTimestampMilli(resultSet, 14);
Long onlineAccountsTimestamp = resultSet.getLong(14);
if (onlineAccountsTimestamp == 0 && resultSet.wasNull())
onlineAccountsTimestamp = null;
byte[] onlineAccountsSignatures = resultSet.getBytes(15);
return new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp,
@ -61,7 +62,9 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public BlockData fromSignature(byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE signature = ? LIMIT 1", signature)) {
String sql = "SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE signature = ? LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql, signature)) {
return getBlockFromResultSet(resultSet);
} catch (SQLException e) {
throw new DataException("Error fetching block by signature from repository", e);
@ -70,7 +73,9 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public BlockData fromReference(byte[] reference) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE reference = ? LIMIT 1", reference)) {
String sql = "SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE reference = ? LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql, reference)) {
return getBlockFromResultSet(resultSet);
} catch (SQLException e) {
throw new DataException("Error fetching block by reference from repository", e);
@ -79,7 +84,9 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public BlockData fromHeight(int height) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE height = ? LIMIT 1", height)) {
String sql = "SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE height = ? LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql, height)) {
return getBlockFromResultSet(resultSet);
} catch (SQLException e) {
throw new DataException("Error fetching block by height from repository", e);
@ -97,7 +104,9 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public int getHeightFromSignature(byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT height FROM Blocks WHERE signature = ? LIMIT 1", signature)) {
String sql = "SELECT height FROM Blocks WHERE signature = ? LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql, signature)) {
if (resultSet == null)
return 0;
@ -109,9 +118,10 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public int getHeightFromTimestamp(long timestamp) throws DataException {
// Uses (minted, height) index
try (ResultSet resultSet = this.repository.checkedExecute("SELECT height FROM Blocks WHERE minted <= ? ORDER BY minted DESC LIMIT 1",
toOffsetDateTime(timestamp))) {
// Uses (minted_when, height) index
String sql = "SELECT height FROM Blocks WHERE minted_when <= ? ORDER BY minted_when DESC LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql, timestamp)) {
if (resultSet == null)
return 0;
@ -123,7 +133,9 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public int getBlockchainHeight() throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT height FROM Blocks ORDER BY height DESC LIMIT 1")) {
String sql = "SELECT height FROM Blocks ORDER BY height DESC LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql)) {
if (resultSet == null)
return 0;
@ -135,7 +147,9 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public BlockData getLastBlock() throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks ORDER BY height DESC LIMIT 1")) {
String sql = "SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks ORDER BY height DESC LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql)) {
return getBlockFromResultSet(resultSet);
} catch (SQLException e) {
throw new DataException("Error fetching last block from repository", e);
@ -176,7 +190,9 @@ public class HSQLDBBlockRepository implements BlockRepository {
public int countMintedBlocks(byte[] minterPublicKey) throws DataException {
String directSql = "SELECT COUNT(*) FROM Blocks WHERE minter = ?";
String rewardShareSql = "SELECT COUNT(*) FROM RewardShares JOIN Blocks ON minter = reward_share_public_key WHERE minter_public_key = ?";
String rewardShareSql = "SELECT COUNT(*) FROM RewardShares "
+ "JOIN Blocks ON minter = reward_share_public_key "
+ "WHERE minter_public_key = ?";
int totalCount = 0;
@ -346,10 +362,10 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override
public int trimOldOnlineAccountsSignatures(long timestamp) throws DataException {
String sql = "UPDATE Blocks set online_accounts_signatures = NULL WHERE minted < ? AND online_accounts_signatures IS NOT NULL";
String sql = "UPDATE Blocks set online_accounts_signatures = NULL WHERE minted_when < ? AND online_accounts_signatures IS NOT NULL";
try {
return this.repository.checkedExecuteUpdateCount(sql, toOffsetDateTime(timestamp));
return this.repository.checkedExecuteUpdateCount(sql, timestamp);
} catch (SQLException e) {
throw new DataException("Unable to trim old online accounts signatures in repository", e);
}
@ -377,11 +393,11 @@ public class HSQLDBBlockRepository implements BlockRepository {
saveHelper.bind("signature", blockData.getSignature()).bind("version", blockData.getVersion()).bind("reference", blockData.getReference())
.bind("transaction_count", blockData.getTransactionCount()).bind("total_fees", blockData.getTotalFees())
.bind("transactions_signature", blockData.getTransactionsSignature()).bind("height", blockData.getHeight())
.bind("minted", toOffsetDateTime(blockData.getTimestamp()))
.bind("minted_when", blockData.getTimestamp())
.bind("minter", blockData.getMinterPublicKey()).bind("minter_signature", blockData.getMinterSignature())
.bind("AT_count", blockData.getATCount()).bind("AT_fees", blockData.getATFees())
.bind("online_accounts", blockData.getEncodedOnlineAccounts()).bind("online_accounts_count", blockData.getOnlineAccountsCount())
.bind("online_accounts_timestamp", toOffsetDateTime(blockData.getOnlineAccountsTimestamp()))
.bind("online_accounts_timestamp", blockData.getOnlineAccountsTimestamp())
.bind("online_accounts_signatures", blockData.getOnlineAccountsSignatures());
try {

View File

@ -43,13 +43,13 @@ public class HSQLDBChatRepository implements ChatRepository {
// Timestamp range
if (before != null) {
whereClauses.add("Transactions.creation < ?");
bindParams.add(HSQLDBRepository.toOffsetDateTime(before));
whereClauses.add("Transactions.created_when < ?");
bindParams.add(before);
}
if (after != null) {
whereClauses.add("Transactions.creation > ?");
bindParams.add(HSQLDBRepository.toOffsetDateTime(after));
whereClauses.add("Transactions.created_when > ?");
bindParams.add(after);
}
if (txGroupId != null)
@ -83,7 +83,7 @@ public class HSQLDBChatRepository implements ChatRepository {
}
}
sql.append(" ORDER BY Transactions.creation");
sql.append(" ORDER BY Transactions.created_when");
sql.append((reverse == null || !reverse) ? " ASC" : " DESC");
HSQLDBRepository.limitOffsetSql(sql, limit, offset);

View File

@ -2,9 +2,7 @@ package org.qortal.repository.hsqldb;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.qortal.data.group.GroupAdminData;
@ -29,7 +27,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupData fromGroupId(int groupId) throws DataException {
String sql = "SELECT group_name, owner, description, created, updated, reference, is_open, approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups WHERE group_id = ?";
String sql = "SELECT group_name, owner, description, created_when, updated_when, reference, is_open, "
+ "approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups WHERE group_id = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, groupId)) {
if (resultSet == null)
@ -38,11 +37,12 @@ public class HSQLDBGroupRepository implements GroupRepository {
String groupName = resultSet.getString(1);
String owner = resultSet.getString(2);
String description = resultSet.getString(3);
long created = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long created = resultSet.getLong(4);
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
Long updated = resultSet.getLong(5);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
@ -54,7 +54,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
int creationGroupId = resultSet.getInt(11);
return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId);
return new GroupData(groupId, owner, groupName, description, created, updated, isOpen,
approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId);
} catch (SQLException e) {
throw new DataException("Unable to fetch group info from repository", e);
}
@ -62,7 +63,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupData fromGroupName(String groupName) throws DataException {
String sql = "SELECT group_id, owner, description, created, updated, reference, is_open, approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups WHERE group_name = ?";
String sql = "SELECT group_id, owner, description, created_when, updated_when, reference, is_open, "
+ "approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups WHERE group_name = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, groupName)) {
if (resultSet == null)
@ -71,11 +73,12 @@ public class HSQLDBGroupRepository implements GroupRepository {
int groupId = resultSet.getInt(1);
String owner = resultSet.getString(2);
String description = resultSet.getString(3);
long created = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long created = resultSet.getLong(4);
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
Long updated = resultSet.getLong(5);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
@ -87,7 +90,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
int creationGroupId = resultSet.getInt(11);
return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId);
return new GroupData(groupId, owner, groupName, description, created, updated, isOpen,
approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId);
} catch (SQLException e) {
throw new DataException("Unable to fetch group info from repository", e);
}
@ -114,8 +118,10 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupData> getAllGroups(Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT group_id, owner, group_name, description, created, updated, reference, is_open, "
sql.append("SELECT group_id, owner, group_name, description, created_when, updated_when, reference, is_open, "
+ "approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups ORDER BY group_name");
if (reverse != null && reverse)
sql.append(" DESC");
@ -132,11 +138,12 @@ public class HSQLDBGroupRepository implements GroupRepository {
String owner = resultSet.getString(2);
String groupName = resultSet.getString(3);
String description = resultSet.getString(4);
long created = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long created = resultSet.getLong(5);
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(6, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
Long updated = resultSet.getLong(6);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(7);
boolean isOpen = resultSet.getBoolean(8);
@ -148,7 +155,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
int creationGroupId = resultSet.getInt(12);
groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId));
groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen,
approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId));
} while (resultSet.next());
return groups;
@ -160,8 +168,10 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupData> getGroupsByOwner(String owner, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT group_id, group_name, description, created, updated, reference, is_open, "
sql.append("SELECT group_id, group_name, description, created_when, updated_when, reference, is_open, "
+ "approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups WHERE owner = ? ORDER BY group_name");
if (reverse != null && reverse)
sql.append(" DESC");
@ -177,11 +187,12 @@ public class HSQLDBGroupRepository implements GroupRepository {
int groupId = resultSet.getInt(1);
String groupName = resultSet.getString(2);
String description = resultSet.getString(3);
long created = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long created = resultSet.getLong(4);
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
Long updated = resultSet.getLong(5);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
@ -193,7 +204,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
int creationGroupId = resultSet.getInt(11);
groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId));
groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen,
approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId));
} while (resultSet.next());
return groups;
@ -205,11 +217,13 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupData> getGroupsWithMember(String member, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT group_id, owner, group_name, description, created, updated, reference, is_open, "
sql.append("SELECT group_id, owner, group_name, description, created_when, updated_when, reference, is_open, "
+ "approval_threshold, min_block_delay, max_block_delay, creation_group_id, admin FROM Groups "
+ "JOIN GroupMembers USING (group_id) "
+ "LEFT OUTER JOIN GroupAdmins ON GroupAdmins.group_id = GroupMembers.group_id AND GroupAdmins.admin = GroupMembers.address "
+ "WHERE address = ? ORDER BY group_name");
if (reverse != null && reverse)
sql.append(" DESC");
@ -226,11 +240,12 @@ public class HSQLDBGroupRepository implements GroupRepository {
String owner = resultSet.getString(2);
String groupName = resultSet.getString(3);
String description = resultSet.getString(4);
long created = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long created = resultSet.getLong(5);
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(6, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
Long updated = resultSet.getLong(6);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(7);
boolean isOpen = resultSet.getBoolean(8);
@ -241,10 +256,13 @@ public class HSQLDBGroupRepository implements GroupRepository {
int maxBlockDelay = resultSet.getInt(11);
int creationGroupId = resultSet.getInt(12);
resultSet.getString(13);
resultSet.getString(13); // 'admin'
boolean isAdmin = !resultSet.wasNull();
GroupData groupData = new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId);
GroupData groupData = new GroupData(groupId, owner, groupName, description, created, updated, isOpen,
approvalThreshold, minBlockDelay, maxBlockDelay, reference, creationGroupId);
groupData.setIsAdmin(isAdmin);
groups.add(groupData);
@ -260,12 +278,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
public void save(GroupData groupData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("Groups");
// Special handling for "updated" timestamp
Long updated = groupData.getUpdated();
Timestamp updatedTimestamp = updated == null ? null : new Timestamp(updated);
saveHelper.bind("group_id", groupData.getGroupId()).bind("owner", groupData.getOwner()).bind("group_name", groupData.getGroupName())
.bind("description", groupData.getDescription()).bind("created", new Timestamp(groupData.getCreated())).bind("updated", updatedTimestamp)
.bind("description", groupData.getDescription()).bind("created_when", groupData.getCreated()).bind("updated_when", groupData.getUpdated())
.bind("reference", groupData.getReference()).bind("is_open", groupData.getIsOpen()).bind("approval_threshold", groupData.getApprovalThreshold().value)
.bind("min_block_delay", groupData.getMinimumBlockDelay()).bind("max_block_delay", groupData.getMaximumBlockDelay())
.bind("creation_group_id", groupData.getCreationGroupId());
@ -350,7 +364,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupAdminData> getGroupAdmins(int groupId, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT admin, reference FROM GroupAdmins WHERE group_id = ? ORDER BY admin");
if (reverse != null && reverse)
sql.append(" DESC");
@ -416,14 +432,14 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupMemberData getMember(int groupId, String address) throws DataException {
String sql = "SELECT address, joined, reference FROM GroupMembers WHERE group_id = ?";
String sql = "SELECT address, joined_when, reference FROM GroupMembers WHERE group_id = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, groupId)) {
if (resultSet == null)
return null;
String member = resultSet.getString(1);
long joined = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long joined = resultSet.getLong(2);
byte[] reference = resultSet.getBytes(3);
return new GroupMemberData(groupId, member, joined, reference);
@ -444,7 +460,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupMemberData> getGroupMembers(int groupId, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT address, joined, reference FROM GroupMembers WHERE group_id = ? ORDER BY address");
sql.append("SELECT address, joined_when, reference FROM GroupMembers WHERE group_id = ? ORDER BY address");
if (reverse != null && reverse)
sql.append(" DESC");
@ -458,7 +476,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
do {
String member = resultSet.getString(1);
long joined = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long joined = resultSet.getLong(2);
byte[] reference = resultSet.getBytes(3);
members.add(new GroupMemberData(groupId, member, joined, reference));
@ -490,7 +508,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupMembers");
saveHelper.bind("group_id", groupMemberData.getGroupId()).bind("address", groupMemberData.getMember())
.bind("joined", new Timestamp(groupMemberData.getJoined())).bind("reference", groupMemberData.getReference());
.bind("joined_when", groupMemberData.getJoined()).bind("reference", groupMemberData.getReference());
try {
saveHelper.execute(this.repository);
@ -512,15 +530,17 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupInviteData getInvite(int groupId, String invitee) throws DataException {
String sql = "SELECT inviter, expiry, reference FROM GroupInvites WHERE group_id = ? AND invitee = ?";
String sql = "SELECT inviter, expires_when, reference FROM GroupInvites WHERE group_id = ? AND invitee = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, groupId, invitee)) {
if (resultSet == null)
return null;
String inviter = resultSet.getString(1);
Timestamp expiryTimestamp = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
Long expiry = resultSet.getLong(2);
if (expiry == 0 && resultSet.wasNull())
expiry = null;
byte[] reference = resultSet.getBytes(3);
@ -542,7 +562,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupInviteData> getInvitesByGroupId(int groupId, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT inviter, invitee, expiry, reference FROM GroupInvites WHERE group_id = ? ORDER BY invitee");
sql.append("SELECT inviter, invitee, expires_when, reference FROM GroupInvites WHERE group_id = ? ORDER BY invitee");
if (reverse != null && reverse)
sql.append(" DESC");
@ -558,8 +580,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
String inviter = resultSet.getString(1);
String invitee = resultSet.getString(2);
Timestamp expiryTimestamp = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
Long expiry = resultSet.getLong(3);
if (expiry == 0 && resultSet.wasNull())
expiry = null;
byte[] reference = resultSet.getBytes(4);
@ -575,7 +598,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupInviteData> getInvitesByInvitee(String invitee, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT group_id, inviter, expiry, reference FROM GroupInvites WHERE invitee = ? ORDER BY group_id");
sql.append("SELECT group_id, inviter, expires_when, reference FROM GroupInvites WHERE invitee = ? ORDER BY group_id");
if (reverse != null && reverse)
sql.append(" DESC");
@ -591,8 +616,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
int groupId = resultSet.getInt(1);
String inviter = resultSet.getString(2);
Timestamp expiryTimestamp = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
Long expiry = resultSet.getLong(3);
if (expiry == 0 && resultSet.wasNull())
expiry = null;
byte[] reference = resultSet.getBytes(4);
@ -609,12 +635,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
public void save(GroupInviteData groupInviteData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupInvites");
Timestamp expiryTimestamp = null;
if (groupInviteData.getExpiry() != null)
expiryTimestamp = new Timestamp(groupInviteData.getExpiry());
saveHelper.bind("group_id", groupInviteData.getGroupId()).bind("inviter", groupInviteData.getInviter()).bind("invitee", groupInviteData.getInvitee())
.bind("expiry", expiryTimestamp).bind("reference", groupInviteData.getReference());
saveHelper.bind("group_id", groupInviteData.getGroupId()).bind("inviter", groupInviteData.getInviter())
.bind("invitee", groupInviteData.getInvitee()).bind("expires_when", groupInviteData.getExpiry())
.bind("reference", groupInviteData.getReference());
try {
saveHelper.execute(this.repository);
@ -662,7 +685,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupJoinRequestData> getGroupJoinRequests(int groupId, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT joiner, reference FROM GroupJoinRequests WHERE group_id = ? ORDER BY joiner");
if (reverse != null && reverse)
sql.append(" DESC");
@ -691,8 +716,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
public void save(GroupJoinRequestData groupJoinRequestData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupJoinRequests");
saveHelper.bind("group_id", groupJoinRequestData.getGroupId()).bind("joiner", groupJoinRequestData.getJoiner()).bind("reference",
groupJoinRequestData.getReference());
saveHelper.bind("group_id", groupJoinRequestData.getGroupId()).bind("joiner", groupJoinRequestData.getJoiner())
.bind("reference", groupJoinRequestData.getReference());
try {
saveHelper.execute(this.repository);
@ -714,15 +739,16 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupBanData getBan(int groupId, String offender) throws DataException {
String sql = "SELECT admin, banned, reason, expiry, reference FROM GroupBans WHERE group_id = ? AND offender = ?";
String sql = "SELECT admin, banned_when, reason, expires_when, reference FROM GroupBans WHERE group_id = ? AND offender = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, groupId, offender)) {
String admin = resultSet.getString(1);
long banned = resultSet.getTimestamp(2, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long banned = resultSet.getLong(2);
String reason = resultSet.getString(3);
Timestamp expiryTimestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
Long expiry = resultSet.getLong(4);
if (expiry == 0 && resultSet.wasNull())
expiry = null;
byte[] reference = resultSet.getBytes(5);
@ -744,7 +770,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List<GroupBanData> getGroupBans(int groupId, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT offender, admin, banned, reason, expiry, reference FROM GroupBans WHERE group_id = ? ORDER BY offender");
sql.append("SELECT offender, admin, banned_when, reason, expires_when, reference FROM GroupBans WHERE group_id = ? ORDER BY offender");
if (reverse != null && reverse)
sql.append(" DESC");
@ -759,11 +787,12 @@ public class HSQLDBGroupRepository implements GroupRepository {
do {
String offender = resultSet.getString(1);
String admin = resultSet.getString(2);
long banned = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long banned = resultSet.getLong(3);
String reason = resultSet.getString(4);
Timestamp expiryTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long expiry = expiryTimestamp == null ? null : expiryTimestamp.getTime();
Long expiry = resultSet.getLong(5);
if (expiry == 0 && resultSet.wasNull())
expiry = null;
byte[] reference = resultSet.getBytes(6);
@ -780,12 +809,8 @@ public class HSQLDBGroupRepository implements GroupRepository {
public void save(GroupBanData groupBanData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupBans");
Timestamp expiryTimestamp = null;
if (groupBanData.getExpiry() != null)
expiryTimestamp = new Timestamp(groupBanData.getExpiry());
saveHelper.bind("group_id", groupBanData.getGroupId()).bind("offender", groupBanData.getOffender()).bind("admin", groupBanData.getAdmin())
.bind("banned", new Timestamp(groupBanData.getBanned())).bind("reason", groupBanData.getReason()).bind("expiry", expiryTimestamp)
.bind("banned", groupBanData.getBanned()).bind("reason", groupBanData.getReason()).bind("expiry", groupBanData.getExpiry())
.bind("reference", groupBanData.getReference());
try {

View File

@ -1,13 +1,8 @@
package org.qortal.repository.hsqldb;
import static org.qortal.repository.hsqldb.HSQLDBRepository.getZonedTimestampMilli;
import static org.qortal.repository.hsqldb.HSQLDBRepository.toOffsetDateTime;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.qortal.data.naming.NameData;
@ -24,7 +19,7 @@ public class HSQLDBNameRepository implements NameRepository {
@Override
public NameData fromName(String name) throws DataException {
String sql = "SELECT owner, data, registered, updated, reference, is_for_sale, sale_price, creation_group_id FROM Names WHERE name = ?";
String sql = "SELECT owner, data, registered_when, updated_when, reference, is_for_sale, sale_price, creation_group_id FROM Names WHERE name = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, name)) {
if (resultSet == null)
@ -32,11 +27,12 @@ public class HSQLDBNameRepository implements NameRepository {
String owner = resultSet.getString(1);
String data = resultSet.getString(2);
long registered = resultSet.getTimestamp(3, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long registered = resultSet.getLong(3);
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
Long updated = resultSet.getLong(4);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(5);
boolean isForSale = resultSet.getBoolean(6);
@ -65,7 +61,9 @@ public class HSQLDBNameRepository implements NameRepository {
@Override
public List<NameData> getAllNames(Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT name, data, owner, registered, updated, reference, is_for_sale, sale_price, creation_group_id FROM Names ORDER BY name");
sql.append("SELECT name, data, owner, registered_when, updated_when, reference, is_for_sale, sale_price, creation_group_id FROM Names ORDER BY name");
if (reverse != null && reverse)
sql.append(" DESC");
@ -81,8 +79,13 @@ public class HSQLDBNameRepository implements NameRepository {
String name = resultSet.getString(1);
String data = resultSet.getString(2);
String owner = resultSet.getString(3);
long registered = getZonedTimestampMilli(resultSet, 4);
Long updated = getZonedTimestampMilli(resultSet, 5); // can be null
long registered = resultSet.getLong(4);
// Special handling for possibly-NULL "updated" column
Long updated = resultSet.getLong(5);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(6);
boolean isForSale = resultSet.getBoolean(7);
@ -104,7 +107,9 @@ public class HSQLDBNameRepository implements NameRepository {
@Override
public List<NameData> getNamesForSale(Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT name, data, owner, registered, updated, reference, sale_price, creation_group_id FROM Names WHERE is_for_sale = TRUE ORDER BY name");
sql.append("SELECT name, data, owner, registered_when, updated_when, reference, sale_price, creation_group_id FROM Names WHERE is_for_sale = TRUE ORDER BY name");
if (reverse != null && reverse)
sql.append(" DESC");
@ -120,8 +125,13 @@ public class HSQLDBNameRepository implements NameRepository {
String name = resultSet.getString(1);
String data = resultSet.getString(2);
String owner = resultSet.getString(3);
long registered = getZonedTimestampMilli(resultSet, 4);
Long updated = getZonedTimestampMilli(resultSet, 5); // can be null
long registered = resultSet.getLong(4);
// Special handling for possibly-NULL "updated" column
Long updated = resultSet.getLong(5);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(6);
boolean isForSale = true;
@ -143,7 +153,9 @@ public class HSQLDBNameRepository implements NameRepository {
@Override
public List<NameData> getNamesByOwner(String owner, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512);
sql.append("SELECT name, data, registered, updated, reference, is_for_sale, sale_price, creation_group_id FROM Names WHERE owner = ? ORDER BY name");
sql.append("SELECT name, data, registered_when, updated_when, reference, is_for_sale, sale_price, creation_group_id FROM Names WHERE owner = ? ORDER BY name");
if (reverse != null && reverse)
sql.append(" DESC");
@ -158,8 +170,13 @@ public class HSQLDBNameRepository implements NameRepository {
do {
String name = resultSet.getString(1);
String data = resultSet.getString(2);
long registered = getZonedTimestampMilli(resultSet, 3);
Long updated = getZonedTimestampMilli(resultSet, 4); // can be null
long registered = resultSet.getLong(3);
// Special handling for possibly-NULL "updated" column
Long updated = resultSet.getLong(4);
if (updated == 0 && resultSet.wasNull())
updated = null;
byte[] reference = resultSet.getBytes(5);
boolean isForSale = resultSet.getBoolean(6);
@ -179,14 +196,14 @@ public class HSQLDBNameRepository implements NameRepository {
}
@Override
public List<String> getRecentNames(long start) throws DataException {
public List<String> getRecentNames(long startTimestamp) throws DataException {
String sql = "SELECT name FROM RegisterNameTransactions JOIN Names USING (name) "
+ "JOIN Transactions USING (signature) "
+ "WHERE creation >= ?";
+ "WHERE created_when >= ?";
List<String> names = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql, HSQLDBRepository.toOffsetDateTime(start))) {
try (ResultSet resultSet = this.repository.checkedExecute(sql, startTimestamp)) {
if (resultSet == null)
return names;
@ -207,7 +224,7 @@ public class HSQLDBNameRepository implements NameRepository {
HSQLDBSaver saveHelper = new HSQLDBSaver("Names");
saveHelper.bind("owner", nameData.getOwner()).bind("name", nameData.getName()).bind("data", nameData.getData())
.bind("registered", toOffsetDateTime(nameData.getRegistered())).bind("updated", toOffsetDateTime(nameData.getUpdated()))
.bind("registered_when", nameData.getRegistered()).bind("updated_when", nameData.getUpdated())
.bind("reference", nameData.getReference())
.bind("is_for_sale", nameData.getIsForSale()).bind("sale_price", nameData.getSalePrice())
.bind("creation_group_id", nameData.getCreationGroupId());

View File

@ -33,13 +33,21 @@ public class HSQLDBNetworkRepository implements NetworkRepository {
String address = resultSet.getString(1);
PeerAddress peerAddress = PeerAddress.fromString(address);
Long lastConnected = HSQLDBRepository.getZonedTimestampMilli(resultSet, 2);
Long lastConnected = resultSet.getLong(2);
if (lastConnected == 0 && resultSet.wasNull())
lastConnected = null;
Long lastAttempted = HSQLDBRepository.getZonedTimestampMilli(resultSet, 3);
Long lastAttempted = resultSet.getLong(3);
if (lastAttempted == 0 && resultSet.wasNull())
lastAttempted = null;
Long lastMisbehaved = HSQLDBRepository.getZonedTimestampMilli(resultSet, 4);
Long lastMisbehaved = resultSet.getLong(4);
if (lastMisbehaved == 0 && resultSet.wasNull())
lastMisbehaved = null;
Long addedWhen = HSQLDBRepository.getZonedTimestampMilli(resultSet, 5);
Long addedWhen = resultSet.getLong(5);
if (addedWhen == 0 && resultSet.wasNull())
addedWhen = null;
String addedBy = resultSet.getString(6);
@ -58,11 +66,9 @@ public class HSQLDBNetworkRepository implements NetworkRepository {
public void save(PeerData peerData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("Peers");
saveHelper.bind("address", peerData.getAddress().toString()).bind("last_connected", HSQLDBRepository.toOffsetDateTime(peerData.getLastConnected()))
.bind("last_attempted", HSQLDBRepository.toOffsetDateTime(peerData.getLastAttempted()))
.bind("last_misbehaved", HSQLDBRepository.toOffsetDateTime(peerData.getLastMisbehaved()))
.bind("added_when", HSQLDBRepository.toOffsetDateTime(peerData.getAddedWhen()))
.bind("added_by", peerData.getAddedBy());
saveHelper.bind("address", peerData.getAddress().toString()).bind("last_connected", peerData.getLastConnected())
.bind("last_attempted", peerData.getLastAttempted()).bind("last_misbehaved", peerData.getLastMisbehaved())
.bind("added_when", peerData.getAddedWhen()).bind("added_by", peerData.getAddedBy());
try {
saveHelper.execute(this.repository);

View File

@ -14,22 +14,16 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Deque;
import java.util.List;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.crypto.Crypto;
import org.qortal.repository.ATRepository;
import org.qortal.repository.AccountRepository;
import org.qortal.repository.ArbitraryRepository;
@ -51,8 +45,6 @@ public class HSQLDBRepository implements Repository {
private static final Logger LOGGER = LogManager.getLogger(HSQLDBRepository.class);
public static final TimeZone UTC = TimeZone.getTimeZone("UTC");
protected Connection connection;
protected Deque<Savepoint> savepoints;
protected boolean debugState = false;
@ -78,7 +70,7 @@ public class HSQLDBRepository implements Repository {
try (ResultSet resultSet = stmt.getResultSet()) {
if (resultSet == null || !resultSet.next())
LOGGER.warn("Unable to fetch session ID from repository");
throw new DataException("Unable to fetch session ID from repository");
this.sessionId = resultSet.getLong(1);
}
@ -442,7 +434,7 @@ public class HSQLDBRepository implements Repository {
long queryTime = System.currentTimeMillis() - beforeQuery;
if (queryTime > this.slowQueryThreshold) {
LOGGER.info(String.format("HSQLDB query took %d ms: %s", queryTime, sql), new SQLException("slow query"));
LOGGER.info(() -> String.format("HSQLDB query took %d ms: %s", queryTime, sql), new SQLException("slow query"));
logStatements();
}
@ -517,7 +509,7 @@ public class HSQLDBRepository implements Repository {
long queryTime = System.currentTimeMillis() - beforeQuery;
if (queryTime > this.slowQueryThreshold) {
LOGGER.info(String.format("HSQLDB query took %d ms: %s", queryTime, sql), new SQLException("slow query"));
LOGGER.info(() -> String.format("HSQLDB query took %d ms: %s", queryTime, sql), new SQLException("slow query"));
logStatements();
}
@ -690,7 +682,7 @@ public class HSQLDBRepository implements Repository {
if (this.sqlStatements == null)
return;
LOGGER.info(String.format("HSQLDB SQL statements (session %d) leading up to this were:", this.sessionId));
LOGGER.info(() -> String.format("HSQLDB SQL statements (session %d) leading up to this were:", this.sessionId));
for (String sql : this.sqlStatements)
LOGGER.info(sql);
@ -752,42 +744,4 @@ public class HSQLDBRepository implements Repository {
}
}
// Utility methods
public static byte[] ed25519PrivateToPublicKey(byte[] privateKey) {
if (privateKey == null)
return null;
return PrivateKeyAccount.toPublicKey(privateKey);
}
public static String ed25519PublicKeyToAddress(byte[] publicKey) {
if (publicKey == null)
return null;
return Crypto.toAddress(publicKey);
}
/** Converts milliseconds from epoch to OffsetDateTime needed for TIMESTAMP WITH TIME ZONE columns. */
public static OffsetDateTime toOffsetDateTime(Long timestamp) {
if (timestamp == null)
return null;
return OffsetDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC);
}
/** Converts OffsetDateTime from TIMESTAMP WITH TIME ZONE column to milliseconds from epoch. */
public static long fromOffsetDateTime(OffsetDateTime offsetDateTime) {
return offsetDateTime.toInstant().toEpochMilli();
}
/** Returns TIMESTAMP WITH TIME ZONE column value as milliseconds from epoch, or null. */
public static Long getZonedTimestampMilli(ResultSet resultSet, int columnIndex) throws SQLException {
OffsetDateTime offsetDateTime = resultSet.getObject(columnIndex, OffsetDateTime.class);
if (offsetDateTime == null)
return null;
return offsetDateTime.toInstant().toEpochMilli();
}
}

View File

@ -7,6 +7,7 @@ import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
/**
* Database helper for building, and executing, INSERT INTO ... ON DUPLICATE KEY UPDATE ... statements.
@ -20,6 +21,8 @@ import java.util.List;
*/
public class HSQLDBSaver {
private final Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
private String table;
private List<String> columns = new ArrayList<>();
@ -137,8 +140,8 @@ public class HSQLDBSaver {
preparedStatement.setBigDecimal(i + this.objects.size() + 1, (BigDecimal) object);
} else if (object instanceof Timestamp) {
// Special treatment for Timestamps so that they are stored as UTC
preparedStatement.setTimestamp(i + 1, (Timestamp) object, Calendar.getInstance(HSQLDBRepository.UTC));
preparedStatement.setTimestamp(i + this.objects.size() + 1, (Timestamp) object, Calendar.getInstance(HSQLDBRepository.UTC));
preparedStatement.setTimestamp(i + 1, (Timestamp) object, utcCalendar);
preparedStatement.setTimestamp(i + this.objects.size() + 1, (Timestamp) object, utcCalendar);
} else {
preparedStatement.setObject(i + 1, object);
preparedStatement.setObject(i + this.objects.size() + 1, object);

View File

@ -2,9 +2,7 @@ package org.qortal.repository.hsqldb;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.qortal.data.voting.PollData;
@ -25,7 +23,7 @@ public class HSQLDBVotingRepository implements VotingRepository {
@Override
public PollData fromPollName(String pollName) throws DataException {
String sql = "SELECT description, creator, owner, published FROM Polls WHERE poll_name = ?";
String sql = "SELECT description, creator, owner, published_when FROM Polls WHERE poll_name = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, pollName)) {
if (resultSet == null)
@ -34,7 +32,7 @@ public class HSQLDBVotingRepository implements VotingRepository {
String description = resultSet.getString(1);
byte[] creatorPublicKey = resultSet.getBytes(2);
String owner = resultSet.getString(3);
long published = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
long published = resultSet.getLong(4);
String optionsSql = "SELECT option_name FROM PollOptions WHERE poll_name = ? ORDER BY option_index ASC";
try (ResultSet optionsResultSet = this.repository.checkedExecute(optionsSql, pollName)) {
@ -71,7 +69,7 @@ public class HSQLDBVotingRepository implements VotingRepository {
HSQLDBSaver saveHelper = new HSQLDBSaver("Polls");
saveHelper.bind("poll_name", pollData.getPollName()).bind("description", pollData.getDescription()).bind("creator", pollData.getCreatorPublicKey())
.bind("owner", pollData.getOwner()).bind("published", new Timestamp(pollData.getPublished()));
.bind("owner", pollData.getOwner()).bind("published_when", pollData.getPublished());
try {
saveHelper.execute(this.repository);

View File

@ -1,8 +1,5 @@
package org.qortal.repository.hsqldb.transaction;
import static org.qortal.repository.hsqldb.HSQLDBRepository.getZonedTimestampMilli;
import static org.qortal.repository.hsqldb.HSQLDBRepository.toOffsetDateTime;
import static org.qortal.transaction.Transaction.TransactionType.*;
import java.lang.reflect.Constructor;
@ -124,7 +121,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
@Override
public TransactionData fromSignature(byte[] signature) throws DataException {
String sql = "SELECT type, reference, creator, creation, fee, tx_group_id, block_height, approval_status, approval_height "
String sql = "SELECT type, reference, creator, created_when, fee, tx_group_id, block_height, approval_status, approval_height "
+ "FROM Transactions WHERE signature = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, signature)) {
@ -135,7 +132,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
byte[] reference = resultSet.getBytes(2);
byte[] creatorPublicKey = resultSet.getBytes(3);
long timestamp = getZonedTimestampMilli(resultSet, 4);
long timestamp = resultSet.getLong(4);
Long fee = resultSet.getLong(5);
if (fee == 0 && resultSet.wasNull())
@ -161,7 +158,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
@Override
public TransactionData fromReference(byte[] reference) throws DataException {
String sql = "SELECT type, signature, creator, creation, fee, tx_group_id, block_height, approval_status, approval_height "
String sql = "SELECT type, signature, creator, created_when, fee, tx_group_id, block_height, approval_status, approval_height "
+ "FROM Transactions WHERE reference = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, reference)) {
@ -172,7 +169,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
byte[] signature = resultSet.getBytes(2);
byte[] creatorPublicKey = resultSet.getBytes(3);
long timestamp = getZonedTimestampMilli(resultSet, 4);
long timestamp = resultSet.getLong(4);
Long fee = resultSet.getLong(5);
if (fee == 0 && resultSet.wasNull())
@ -410,7 +407,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
if (hasAddress) {
tables.append(" JOIN TransactionParticipants ON TransactionParticipants.signature = Transactions.signature");
groupBy = " GROUP BY TransactionParticipants.signature, Transactions.creation";
groupBy = " GROUP BY TransactionParticipants.signature, Transactions.created_when";
signatureColumn = "TransactionParticipants.signature";
}
@ -497,7 +494,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
if (groupBy != null)
sql.append(groupBy);
sql.append(" ORDER BY Transactions.creation");
sql.append(" ORDER BY Transactions.created_when");
sql.append((reverse == null || !reverse) ? " ASC" : " DESC");
HSQLDBRepository.limitOffsetSql(sql, limit, offset);
@ -553,7 +550,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
// Enum int value safe to use literally
sql.append(ApprovalStatus.APPROVED.value);
sql.append(" ORDER BY creation DESC LIMIT 1");
sql.append(" ORDER BY created_when DESC LIMIT 1");
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) {
if (resultSet == null)
@ -620,7 +617,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
sql.append(" OR AssetOrders.want_asset_id = ");
sql.append(assetId);
sql.append(") GROUP BY Transactions.signature, Transactions.creation ORDER BY Transactions.creation");
sql.append(") GROUP BY Transactions.signature, Transactions.created_when ORDER BY Transactions.created_when");
sql.append((reverse == null || !reverse) ? " ASC" : " DESC");
HSQLDBRepository.limitOffsetSql(sql, limit, offset);
@ -655,7 +652,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
List<Object> bindParams = new ArrayList<>(3);
StringBuilder sql = new StringBuilder(1024);
sql.append("SELECT creation, tx_group_id, reference, fee, signature, sender, block_height, approval_status, approval_height, recipient, amount, asset_name "
sql.append("SELECT created_when, tx_group_id, reference, fee, signature, sender, block_height, approval_status, approval_height, recipient, amount, asset_name "
+ "FROM TransferAssetTransactions JOIN Transactions USING (signature) ");
if (address != null)
@ -669,7 +666,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
bindParams.add(address);
}
sql.append(" ORDER by creation ");
sql.append(" ORDER by created_when ");
sql.append((reverse == null || !reverse) ? "ASC" : "DESC");
HSQLDBRepository.limitOffsetSql(sql, limit, offset);
@ -681,7 +678,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
return assetTransfers;
do {
long timestamp = getZonedTimestampMilli(resultSet, 1);
long timestamp = resultSet.getLong(1);
int txGroupId = resultSet.getInt(2);
byte[] reference = resultSet.getBytes(3);
long fee = resultSet.getLong(4);
@ -729,7 +726,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
bindParams = new Object[0];
}
sql.append(" ORDER BY creation");
sql.append(" ORDER BY created_when");
if (reverse != null && reverse)
sql.append(" DESC");
@ -867,7 +864,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
String sql = "SELECT signature FROM GroupApprovalTransactions "
+ "NATURAL JOIN Transactions "
+ "WHERE pending_signature = ? AND admin = ? AND block_height IS NOT NULL "
+ "ORDER BY creation DESC, signature DESC LIMIT 1";
+ "ORDER BY created_when DESC, signature DESC LIMIT 1";
try (ResultSet resultSet = this.repository.checkedExecute(sql, pendingSignature, adminPublicKey)) {
if (resultSet == null)
@ -888,7 +885,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
// Also make sure that GROUP_APPROVAL transaction's admin is still an admin of group
// Sub-query SQL to find latest GroupApprovalTransaction relating to passed pending signature
String latestApprovalSql = "SELECT pending_signature, admin, approval, creation, signature FROM GroupApprovalTransactions "
String latestApprovalSql = "SELECT pending_signature, admin, approval, created_when, signature FROM GroupApprovalTransactions "
+ "NATURAL JOIN Transactions WHERE pending_signature = ? AND block_height IS NOT NULL";
StringBuilder sql = new StringBuilder(1024);
@ -896,7 +893,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
sql.append(latestApprovalSql);
sql.append(") AS GAT LEFT OUTER JOIN (");
sql.append(latestApprovalSql);
sql.append(") AS NewerGAT ON NewerGAT.admin = GAT.admin AND (NewerGAT.creation > GAT.creation OR (NewerGAT.creation = GAT.creation AND NewerGat.signature > GAT.signature)) "
sql.append(") AS NewerGAT ON NewerGAT.admin = GAT.admin AND (NewerGAT.created_when > GAT.created_when OR (NewerGAT.created_when = GAT.created_when AND NewerGat.signature > GAT.signature)) "
+ "JOIN Transactions AS PendingTransactions ON PendingTransactions.signature = GAT.pending_signature "
+ "LEFT OUTER JOIN Accounts ON Accounts.public_key = GAT.admin "
+ "LEFT OUTER JOIN GroupAdmins ON GroupAdmins.admin = Accounts.account AND GroupAdmins.group_id = PendingTransactions.tx_group_id "
@ -935,7 +932,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
@Override
public List<byte[]> getUnconfirmedTransactionSignatures() throws DataException {
String sql = "SELECT signature FROM UnconfirmedTransactions ORDER by creation DESC, signature DESC";
String sql = "SELECT signature FROM UnconfirmedTransactions ORDER by created_when DESC, signature DESC";
List<byte[]> signatures = new ArrayList<>();
@ -961,7 +958,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
StringBuilder sql = new StringBuilder(256);
sql.append("SELECT signature FROM UnconfirmedTransactions ");
sql.append("ORDER BY creation");
sql.append("ORDER BY created_when");
if (reverse != null && reverse)
sql.append(" DESC");
@ -1035,7 +1032,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
public void unconfirmTransaction(TransactionData transactionData) throws DataException {
HSQLDBSaver saver = new HSQLDBSaver("UnconfirmedTransactions");
saver.bind("signature", transactionData.getSignature()).bind("creation", toOffsetDateTime(transactionData.getTimestamp()));
saver.bind("signature", transactionData.getSignature()).bind("created_when", transactionData.getTimestamp());
try {
saver.execute(repository);
@ -1052,8 +1049,8 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
saver.bind("signature", transactionData.getSignature()).bind("reference", transactionData.getReference())
.bind("type", transactionData.getType().value)
.bind("creator", transactionData.getCreatorPublicKey()).bind("creation", toOffsetDateTime(transactionData.getTimestamp()))
.bind("fee", transactionData.getFee()).bind("milestone_block", null).bind("tx_group_id", transactionData.getTxGroupId())
.bind("creator", transactionData.getCreatorPublicKey()).bind("created_when", transactionData.getTimestamp())
.bind("fee", transactionData.getFee()).bind("tx_group_id", transactionData.getTxGroupId())
.bind("approval_status", transactionData.getApprovalStatus().value);
try {

View File

@ -23,6 +23,11 @@ public class AddressesApiTests extends ApiCommon {
assertNotNull(this.addressesResource.getAccountInfo(aliceAddress));
}
@Test
public void testGetOnlineAccounts() {
assertNotNull(this.addressesResource.getOnlineAccounts());
}
@Test
public void testGetRewardShares() {
assertNotNull(this.addressesResource.getRewardShares(Collections.singletonList(aliceAddress), null, null, null, null, null));

View File

@ -26,4 +26,9 @@ public class AdminApiTests extends ApiCommon {
assertNotNull(this.adminResource.summary());
}
@Test
public void testGetMintingAccounts() {
assertNotNull(this.adminResource.getMintingAccounts());
}
}

View File

@ -0,0 +1,43 @@
package org.qortal.test.api;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.qortal.api.resource.ArbitraryResource;
import org.qortal.api.resource.TransactionsResource.ConfirmationStatus;
import org.qortal.test.common.ApiCommon;
public class ArbitraryApiTests extends ApiCommon {
private ArbitraryResource arbitraryResource;
@Before
public void buildResource() {
this.arbitraryResource = (ArbitraryResource) ApiCommon.buildResource(ArbitraryResource.class);
}
@Test
public void testSearch() {
Integer[] startingBlocks = new Integer[] { null, 0, 1, 999999999 };
Integer[] blockLimits = new Integer[] { null, 0, 1, 999999999 };
Integer[] txGroupIds = new Integer[] { null, 0, 1, 999999999 };
Integer[] services = new Integer[] { null, 0, 1, 999999999 };
String[] addresses = new String[] { null, this.aliceAddress };
ConfirmationStatus[] confirmationStatuses = new ConfirmationStatus[] { ConfirmationStatus.UNCONFIRMED, ConfirmationStatus.CONFIRMED, ConfirmationStatus.BOTH };
for (Integer startBlock : startingBlocks)
for (Integer blockLimit : blockLimits)
for (Integer txGroupId : txGroupIds)
for (Integer service : services)
for (String address : addresses)
for (ConfirmationStatus confirmationStatus : confirmationStatuses) {
if (confirmationStatus != ConfirmationStatus.CONFIRMED && (startBlock != null || blockLimit != null))
continue;
assertNotNull(this.arbitraryResource.searchTransactions(startBlock, blockLimit, txGroupId, service, address, confirmationStatus, 20, null, null));
assertNotNull(this.arbitraryResource.searchTransactions(startBlock, blockLimit, txGroupId, service, address, confirmationStatus, 1, 1, true));
}
}
}

View File

@ -12,8 +12,12 @@ import org.qortal.api.ApiError;
import org.qortal.api.ApiException;
import org.qortal.api.resource.AssetsResource;
import org.qortal.api.resource.TransactionsResource.ConfirmationStatus;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.repository.AccountRepository.BalanceOrdering;
import org.qortal.repository.DataException;
import org.qortal.test.common.ApiCommon;
import org.qortal.test.common.AssetUtils;
public class AssetsApiTests extends ApiCommon {
@ -22,12 +26,22 @@ public class AssetsApiTests extends ApiCommon {
private AssetsResource assetsResource;
@Before
public void buildResource() {
public void buildResource() throws DataException {
this.assetsResource = (AssetsResource) ApiCommon.buildResource(AssetsResource.class);
// Create some dummy data
try (final Repository repository = RepositoryManager.getRepository()) {
// Matching orders, to create a trade
AssetUtils.createOrder(repository, "alice", AssetUtils.goldAssetId, AssetUtils.otherAssetId, 1_00000000L, 1_00000000L);
AssetUtils.createOrder(repository, "bob", AssetUtils.otherAssetId, AssetUtils.goldAssetId, 1_00000000L, 1_00000000L);
// Open order
AssetUtils.createOrder(repository, "bob", AssetUtils.otherAssetId, AssetUtils.testAssetId, 1_00000000L, 1_00000000L);
}
}
@Test
public void testGet() {
public void testResource() {
assertNotNull(this.assetsResource);
}
@ -70,8 +84,8 @@ public class AssetsApiTests extends ApiCommon {
@Test
public void testGetAssetBalances() {
List<String> addresses = Arrays.asList(aliceAddress, aliceAddress);
List<Long> assetIds = Arrays.asList(1L, 2L, 3L);
List<String> addresses = Arrays.asList(aliceAddress, bobAddress);
List<Long> assetIds = Arrays.asList(0L, 1L, 2L, 3L);
for (BalanceOrdering balanceOrdering : BalanceOrdering.values()) {
for (Boolean excludeZero : ALL_BOOLEAN_VALUES) {

View File

@ -8,8 +8,16 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.api.resource.BlocksResource;
import org.qortal.block.GenesisBlock;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.test.common.ApiCommon;
import org.qortal.test.common.BlockUtils;
import org.qortal.test.common.Common;
import org.qortal.utils.Base58;
public class BlockApiTests extends ApiCommon {
@ -21,24 +29,84 @@ public class BlockApiTests extends ApiCommon {
}
@Test
public void test() {
public void testResource() {
assertNotNull(this.blocksResource);
}
@Test
public void testGetBlockMinters() {
List<String> addresses = Arrays.asList(aliceAddress, aliceAddress);
public void testGetBlock() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
byte[] signatureBytes = GenesisBlock.getInstance(repository).getSignature();
String signature = Base58.encode(signatureBytes);
assertNotNull(this.blocksResource.getBlockMinters(Collections.emptyList(), null, null, null));
assertNotNull(this.blocksResource.getBlockMinters(addresses, null, null, null));
assertNotNull(this.blocksResource.getBlockMinters(Collections.emptyList(), 1, 1, true));
assertNotNull(this.blocksResource.getBlockMinters(addresses, 1, 1, true));
assertNotNull(this.blocksResource.getBlock(signature));
}
}
@Test
public void testGetBlockSummariesByMinter() {
assertNotNull(this.blocksResource.getBlockSummariesByMinter(aliceAddress, null, null, null));
assertNotNull(this.blocksResource.getBlockSummariesByMinter(aliceAddress, 1, 1, true));
public void testGetBlockTransactions() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
byte[] signatureBytes = GenesisBlock.getInstance(repository).getSignature();
String signature = Base58.encode(signatureBytes);
assertNotNull(this.blocksResource.getBlockTransactions(signature, null, null, null));
assertNotNull(this.blocksResource.getBlockTransactions(signature, 1, 1, true));
}
}
@Test
public void testGetHeight() {
assertNotNull(this.blocksResource.getHeight());
}
@Test
public void testGetBlockHeight() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
byte[] signatureBytes = GenesisBlock.getInstance(repository).getSignature();
String signature = Base58.encode(signatureBytes);
assertNotNull(this.blocksResource.getHeight(signature));
}
}
@Test
public void testGetBlockByHeight() {
assertNotNull(this.blocksResource.getByHeight(1));
}
@Test
public void testGetBlockByTimestamp() {
assertNotNull(this.blocksResource.getByTimestamp(System.currentTimeMillis()));
}
@Test
public void testGetBlockRange() {
assertNotNull(this.blocksResource.getBlockRange(1, 1));
}
@Test
public void testGetBlockMinters() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount mintingAccount = Common.getTestAccount(repository, "alice-reward-share");
BlockUtils.mintBlock(repository);
List<String> addresses = Arrays.asList(aliceAddress, mintingAccount.getAddress(), bobAddress);
assertNotNull(this.blocksResource.getBlockMinters(Collections.emptyList(), null, null, null));
assertNotNull(this.blocksResource.getBlockMinters(addresses, null, null, null));
assertNotNull(this.blocksResource.getBlockMinters(Collections.emptyList(), 1, 1, true));
assertNotNull(this.blocksResource.getBlockMinters(addresses, 1, 1, true));
}
}
@Test
public void testGetBlockSummariesByMinter() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockUtils.mintBlock(repository);
assertNotNull(this.blocksResource.getBlockSummariesByMinter(aliceAddress, null, null, null));
assertNotNull(this.blocksResource.getBlockSummariesByMinter(aliceAddress, 1, 1, true));
}
}
}

View File

@ -0,0 +1,91 @@
package org.qortal.test.api;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.api.resource.NamesResource;
import org.qortal.data.transaction.RegisterNameTransactionData;
import org.qortal.data.transaction.SellNameTransactionData;
import org.qortal.data.transaction.TransactionData;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.test.common.ApiCommon;
import org.qortal.test.common.Common;
import org.qortal.test.common.TransactionUtils;
import org.qortal.test.common.transaction.TestTransaction;
public class NamesApiTests extends ApiCommon {
private NamesResource namesResource;
@Before
public void before() throws DataException {
Common.useDefaultSettings();
this.namesResource = (NamesResource) ApiCommon.buildResource(NamesResource.class);
}
@Test
public void testResource() {
assertNotNull(this.namesResource);
}
@Test
public void testGetAllNames() {
assertNotNull(this.namesResource.getAllNames(null, null, null));
assertNotNull(this.namesResource.getAllNames(1, 1, true));
}
@Test
public void testGetNamesByAddress() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
assertNotNull(this.namesResource.getNamesByAddress(alice.getAddress(), null, null, null));
assertNotNull(this.namesResource.getNamesByAddress(alice.getAddress(), 1, 1, true));
}
}
@Test
public void testGetName() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
assertNotNull(this.namesResource.getName(name));
}
}
@Test
public void testGetAllAssets() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
long price = 1_23456789L;
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
// Sell-name
transactionData = new SellNameTransactionData(TestTransaction.generateBase(alice), name, price);
TransactionUtils.signAndMint(repository, transactionData, alice);
assertNotNull(this.namesResource.getNamesForSale(null, null, null));
assertNotNull(this.namesResource.getNamesForSale(1, 1, true));
}
}
}

View File

@ -24,12 +24,14 @@ public class ApiCommon extends Common {
private static final FakeRequest FAKE_REQUEST = new FakeRequest();
public String aliceAddress;
public String bobAddress;
@Before
public void beforeTests() throws DataException {
Common.useDefaultSettings();
this.aliceAddress = Common.getTestAccount(null, "alice").getAddress();
this.bobAddress = Common.getTestAccount(null, "bob").getAddress();
}
public static Object buildResource(Class<?> resourceClass) {

View File

@ -0,0 +1,42 @@
package org.qortal.test.naming;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.data.transaction.RegisterNameTransactionData;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.test.common.Common;
import org.qortal.test.common.TransactionUtils;
import org.qortal.test.common.transaction.TestTransaction;
public class MiscTests extends Common {
@Before
public void beforeTest() throws DataException {
Common.useDefaultSettings();
}
@Test
public void testGetRecentNames() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
List<String> recentNames = repository.getNameRepository().getRecentNames(0L);
assertNotNull(recentNames);
assertFalse(recentNames.isEmpty());
}
}
}