diff --git a/pom.xml b/pom.xml
index 9795d39b..812669c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
1.8
1.2.2
28.1-jre
- 2.5.0-fixed
+ 2.5.1
2.5.0
2.29.1
9.4.29.v20200521
diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBATRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBATRepository.java
index 833137a2..bc26ab78 100644
--- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBATRepository.java
+++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBATRepository.java
@@ -269,9 +269,10 @@ public class HSQLDBATRepository implements ATRepository {
String sql = "SELECT height, created_when, state_data, state_hash, fees, is_initial "
+ "FROM ATStates "
+ "WHERE AT_address = ? "
- + "ORDER BY height DESC "
- + "LIMIT 1 "
- + "USING INDEX";
+ // AT_address then height so the compound primary key is used as an index
+ // Both must be the same direction also
+ + "ORDER BY AT_address DESC, height DESC "
+ + "LIMIT 1 ";
try (ResultSet resultSet = this.repository.checkedExecute(sql, atAddress)) {
if (resultSet == null)
@@ -307,7 +308,9 @@ public class HSQLDBATRepository implements ATRepository {
sql.append(minimumFinalHeight);
}
- sql.append( "ORDER BY height DESC "
+ // AT_address then height so the compound primary key is used as an index
+ // Both must be the same direction also
+ sql.append( "ORDER BY AT_address DESC, height DESC "
+ "LIMIT 1 "
+ ") AS FinalATStates "
+ "WHERE code_hash = ? ");
diff --git a/src/test/java/org/qortal/test/RepositoryTests.java b/src/test/java/org/qortal/test/RepositoryTests.java
index 7b20bbd9..be9ff50f 100644
--- a/src/test/java/org/qortal/test/RepositoryTests.java
+++ b/src/test/java/org/qortal/test/RepositoryTests.java
@@ -13,6 +13,7 @@ import org.qortal.test.common.Common;
import static org.junit.Assert.*;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -180,6 +181,44 @@ public class RepositoryTests extends Common {
}
}
+ /** Test HSQLDB bug-fix for INSERT INTO...ON DUPLICATE KEY UPDATE... bug */
+ @Test
+ public void testOnDuplicateKeyUpdateBugFix() throws SQLException, DataException {
+ ResultSet resultSet;
+
+ try (final HSQLDBRepository hsqldb = (HSQLDBRepository) RepositoryManager.getRepository()) {
+ hsqldb.prepareStatement("DROP TABLE IF EXISTS bugtest").execute();
+ hsqldb.prepareStatement("CREATE TABLE bugtest (id INT NOT NULL, counter INT NOT NULL, PRIMARY KEY(id))").execute();
+
+ hsqldb.prepareStatement("INSERT INTO bugtest (id, counter) VALUES (1, 1) ON DUPLICATE KEY UPDATE counter = counter + 1").execute();
+ resultSet = hsqldb.checkedExecute("SELECT counter FROM bugtest WHERE id = 1");
+ assertNotNull(resultSet);
+ assertEquals(1, resultSet.getInt(1));
+
+ hsqldb.prepareStatement("INSERT INTO bugtest (id, counter) VALUES (1, 100) ON DUPLICATE KEY UPDATE counter = counter + 1").execute();
+ resultSet = hsqldb.checkedExecute("SELECT counter FROM bugtest WHERE id = 1");
+ assertNotNull(resultSet);
+ assertEquals(2, resultSet.getInt(1));
+ }
+ }
+
+ /** Test HSQLDB bug-fix for "General Error" in non-fully-qualified columns inside LATERAL() */
+ @Test
+ public void testOnLateralGeneralError() throws SQLException, DataException {
+ try (final HSQLDBRepository hsqldb = (HSQLDBRepository) RepositoryManager.getRepository()) {
+ hsqldb.prepareStatement("DROP TABLE IF EXISTS tableA").execute();
+ hsqldb.prepareStatement("DROP TABLE IF EXISTS tableB").execute();
+ hsqldb.prepareStatement("DROP TABLE IF EXISTS tableC").execute();
+
+ hsqldb.prepareStatement("CREATE TABLE tableA (col1 INT)").execute();
+ hsqldb.prepareStatement("CREATE TABLE tableB (col1 INT)").execute();
+ hsqldb.prepareStatement("CREATE TABLE tableC (col2 INT, PRIMARY KEY (col2))").execute();
+
+ // Prior to bug-fix this would throw a General Error SQL Exception
+ hsqldb.prepareStatement("SELECT col3 FROM tableA JOIN tableB USING (col1) CROSS JOIN LATERAL(SELECT col2 FROM tableC WHERE col2 = col1) AS tableC (col3)").execute();
+ }
+ }
+
public static void hsqldbSleep(int millis) throws SQLException {
System.out.println(String.format("HSQLDB sleep() thread ID: %s", Thread.currentThread().getId()));