diff --git a/src/main/java/org/qora/api/resource/AddressesResource.java b/src/main/java/org/qora/api/resource/AddressesResource.java index 03759b28..113ca6f6 100644 --- a/src/main/java/org/qora/api/resource/AddressesResource.java +++ b/src/main/java/org/qora/api/resource/AddressesResource.java @@ -305,6 +305,7 @@ public class AddressesResource { @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE}) public List getProxying(@QueryParam("proxiedFor") List recipients, @QueryParam("proxiedBy") List forgers, + @QueryParam("involving") List addresses, @Parameter( ref = "limit" ) @QueryParam("limit") Integer limit, @Parameter( @@ -313,7 +314,7 @@ public class AddressesResource { ref = "reverse" ) @QueryParam("reverse") Boolean reverse) { try (final Repository repository = RepositoryManager.getRepository()) { - return repository.getAccountRepository().findProxyAccounts(recipients, forgers, limit, offset, reverse); + return repository.getAccountRepository().findProxyAccounts(recipients, forgers, addresses, limit, offset, reverse); } catch (DataException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } diff --git a/src/main/java/org/qora/repository/AccountRepository.java b/src/main/java/org/qora/repository/AccountRepository.java index fda28639..cd65d979 100644 --- a/src/main/java/org/qora/repository/AccountRepository.java +++ b/src/main/java/org/qora/repository/AccountRepository.java @@ -91,7 +91,7 @@ public interface AccountRepository { public boolean isProxyPublicKey(byte[] publicKey) throws DataException; - public List findProxyAccounts(List recipients, List forgers, Integer limit, Integer offset, Boolean reverse) throws DataException; + public List findProxyAccounts(List recipients, List forgers, List involvedAddresses, Integer limit, Integer offset, Boolean reverse) throws DataException; public void save(ProxyForgerData proxyForgerData) throws DataException; diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java index a626882d..5a2eaa13 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java @@ -17,6 +17,7 @@ import org.qora.repository.AccountRepository; import org.qora.repository.DataException; import static org.qora.repository.hsqldb.HSQLDBRepository.nPlaceholders; +import static org.qora.repository.hsqldb.HSQLDBRepository.nValuesPlaceholders; public class HSQLDBAccountRepository implements AccountRepository { @@ -362,24 +363,35 @@ public class HSQLDBAccountRepository implements AccountRepository { } @Override - public List findProxyAccounts(List recipients, List forgers, Integer limit, Integer offset, Boolean reverse) throws DataException { - String sql = "SELECT forger, recipient, share, proxy_public_key FROM ProxyForgers "; + public List findProxyAccounts(List recipients, List forgers, List involvedAddresses, + Integer limit, Integer offset, Boolean reverse) throws DataException { + String sql = "SELECT DISTINCT forger, recipient, share, proxy_public_key FROM ProxyForgers "; + List args = new ArrayList<>(); - if (!forgers.isEmpty()) { - sql += "JOIN Accounts ON Accounts.public_key = ProxyForgers.forger " - + "WHERE Accounts.account IN (" + nPlaceholders(forgers.size()) + ") "; - args.addAll(forgers); - } + final boolean hasRecipients = recipients != null && !recipients.isEmpty(); + final boolean hasForgers = forgers != null && !forgers.isEmpty(); + final boolean hasInvolved = involvedAddresses != null && !involvedAddresses.isEmpty(); - if (!recipients.isEmpty()) { - sql += forgers.isEmpty() ? "WHERE " : "AND "; - sql += "recipient IN (" + nPlaceholders(recipients.size()) + ") "; + if (hasForgers || hasInvolved) + sql += "JOIN Accounts ON Accounts.public_key = ProxyForgers.forger "; + + if (hasRecipients) { + sql += "JOIN (VALUES " + nValuesPlaceholders(recipients.size()) + ") AS Recipients (address) ON ProxyForgers.recipient = Recipients.address "; args.addAll(recipients); } - sql += "ORDER BY recipient, share"; + if (hasForgers) { + sql += "JOIN (VALUES " + nValuesPlaceholders(forgers.size()) + ") AS Forgers (address) ON Accounts.account = Forgers.address "; + args.addAll(forgers); + } + if (hasInvolved) { + sql += "JOIN (VALUES " + nValuesPlaceholders(involvedAddresses.size()) + ") AS Involved (address) ON Involved.address IN (ProxyForgers.recipient, Accounts.account) "; + args.addAll(involvedAddresses); + } + + sql += "ORDER BY recipient, share"; if (reverse != null && reverse) sql += " DESC"; diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java index 9cc60d5b..87831fd1 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java @@ -534,4 +534,9 @@ public class HSQLDBRepository implements Repository { return String.join(", ", Collections.nCopies(n, "?")); } + /** Convenience method to return n comma-separated, bracketed, placeholders as a string. */ + public static String nValuesPlaceholders(int n) { + return String.join(", ", Collections.nCopies(n, "(?)")); + } + } \ No newline at end of file