[Git][java-team/libpostgresql-jdbc-java][upstream] New upstream version 42.3.5

Christoph Berg (@myon) gitlab at salsa.debian.org
Fri May 6 15:51:54 BST 2022



Christoph Berg pushed to branch upstream at Debian Java Maintainers / libpostgresql-jdbc-java


Commits:
4e9f0e47 by Christoph Berg at 2022-05-06T16:50:56+02:00
New upstream version 42.3.5
- - - - -


12 changed files:

- README.md
- pom.xml
- src/main/java/org/postgresql/PGProperty.java
- src/main/java/org/postgresql/core/PGStream.java
- src/main/java/org/postgresql/hostchooser/HostRequirement.java
- src/main/java/org/postgresql/hostchooser/MultiHostChooser.java
- src/main/java/org/postgresql/jdbc/PgResultSet.java
- src/main/java/org/postgresql/jdbc/TimestampUtils.java
- src/main/java/org/postgresql/util/DriverInfo.java
- src/main/resources/META-INF/MANIFEST.MF
- src/test/java/org/postgresql/test/hostchooser/MultiHostsConnectionTest.java
- src/test/java/org/postgresql/test/jdbc42/TimestampUtilsTest.java


Changes:

=====================================
README.md
=====================================
@@ -122,13 +122,13 @@ In addition to the standard connection parameters the driver supports a number o
 | connectTimeout                | Integer | 10      | The timeout value used for socket connect operations. |
 | socketTimeout                 | Integer | 0       | The timeout value used for socket read operations. |
 | tcpKeepAlive                  | Boolean | false   | Enable or disable TCP keep-alive. |
-| tcpNoDelay                    | Boolean | false   | Enable or disable TCP no delay. |
+| tcpNoDelay                    | Boolean | true    | Enable or disable TCP no delay. |
 | ApplicationName               | String  | PostgreSQL JDBC Driver    | The application name (require server version >= 9.0). If assumeMinServerVersion is set to >= 9.0 this will be sent in the startup packets, otherwise after the connection is made |
 | readOnly                      | Boolean | false   | Puts this connection in read-only mode |
 | disableColumnSanitiser        | Boolean | false   | Enable optimization that disables column name sanitiser |
 | assumeMinServerVersion        | String  | null    | Assume the server is at least that version |
 | currentSchema                 | String  | null    | Specify the schema (or several schema separated by commas) to be set in the search-path |
-| targetServerType              | String  | any     | Specifies what kind of server to connect, possible values: any, master, slave (deprecated), secondary, preferSlave (deprecated), preferSecondary |
+| targetServerType              | String  | any     | Specifies what kind of server to connect, possible values: any, master, slave (deprecated), secondary, preferSlave (deprecated), preferSecondary, preferPrimary |
 | hostRecheckSeconds            | Integer | 10      | Specifies period (seconds) after which the host status is checked again in case it has changed |
 | loadBalanceHosts              | Boolean | false   | If disabled hosts are connected in the given order. If enabled hosts are chosen randomly from the set of suitable candidates |
 | socketFactory                 | String  | null    | Specify a socket factory for socket creation |


=====================================
pom.xml
=====================================
@@ -10,7 +10,7 @@
     <artifactId>postgresql</artifactId>
     <packaging>jar</packaging>
     <name>PostgreSQL JDBC Driver - JDBC 4.2</name>
-    <version>42.3.4</version>
+    <version>42.3.5</version>
     <description>Java JDBC 4.2 (JRE 8+) driver for PostgreSQL database</description>
     <url>https://github.com/pgjdbc/pgjdbc</url>
 


=====================================
src/main/java/org/postgresql/PGProperty.java
=====================================
@@ -693,7 +693,7 @@ public enum PGProperty {
       "any",
       "Specifies what kind of server to connect",
       false,
-      new String [] {"any", "primary", "master", "slave", "secondary",  "preferSlave", "preferSecondary"}),
+      new String [] {"any", "primary", "master", "slave", "secondary",  "preferSlave", "preferSecondary", "preferPrimary"}),
 
   /**
    * Enable or disable TCP keep-alive. The default is {@code false}.
@@ -705,8 +705,8 @@ public enum PGProperty {
 
   TCP_NO_DELAY(
       "tcpNoDelay",
-      "false",
-      "Enable or disable TCP no delay. The default is (@code false}."
+      "true",
+      "Enable or disable TCP no delay. The default is (@code true}."
   ),
   /**
    * Specifies the length to return for types of unknown length.


=====================================
src/main/java/org/postgresql/core/PGStream.java
=====================================
@@ -113,7 +113,7 @@ public class PGStream implements Closeable, Flushable {
     int receiveBufferSize = 1024;
     int soTimeout = 0;
     boolean keepAlive = false;
-    boolean tcpNoDelay = false;
+    boolean tcpNoDelay = true;
 
     /*
     Get the existing values before closing the stream


=====================================
src/main/java/org/postgresql/hostchooser/HostRequirement.java
=====================================
@@ -40,6 +40,11 @@ public enum HostRequirement {
     public boolean allowConnectingTo(/* @Nullable */ HostStatus status) {
       return status != HostStatus.ConnectFail;
     }
+  },
+  preferPrimary {
+    public boolean allowConnectingTo(/* @Nullable */ HostStatus status) {
+      return status != HostStatus.ConnectFail;
+    }
   };
 
   public abstract boolean allowConnectingTo(/* @Nullable */ HostStatus status);


=====================================
src/main/java/org/postgresql/hostchooser/MultiHostChooser.java
=====================================
@@ -14,7 +14,6 @@ import org.postgresql.util.PSQLException;
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Properties;
@@ -47,8 +46,8 @@ class MultiHostChooser implements HostChooser {
       // In case all the candidate hosts are unavailable or do not match, try all the hosts just in case
       List<HostSpec> allHosts = Arrays.asList(hostSpecs);
       if (loadBalance) {
-        allHosts = new ArrayList<HostSpec>(allHosts);
-        Collections.shuffle(allHosts);
+        allHosts = new ArrayList<>(allHosts);
+        shuffle(allHosts);
       }
       res = withReqStatus(targetServerType, allHosts).iterator();
     }
@@ -56,32 +55,33 @@ class MultiHostChooser implements HostChooser {
   }
 
   private Iterator<CandidateHost> candidateIterator() {
-    if (targetServerType != HostRequirement.preferSecondary) {
+    if (   targetServerType != HostRequirement.preferSecondary
+        && targetServerType != HostRequirement.preferPrimary   ) {
       return getCandidateHosts(targetServerType).iterator();
     }
 
+    HostRequirement preferredServerType =
+        targetServerType == HostRequirement.preferSecondary
+          ? HostRequirement.secondary
+          : HostRequirement.primary;
+
     // preferSecondary tries to find secondary hosts first
     // Note: sort does not work here since there are "unknown" hosts,
     // and that "unknown" might turn out to be master, so we should discard that
     // if other secondaries exist
-    List<CandidateHost> secondaries = getCandidateHosts(HostRequirement.secondary);
+    // Same logic as the above works for preferPrimary if we replace "secondary"
+    // with "primary" and vice versa
+    List<CandidateHost> preferred = getCandidateHosts(preferredServerType);
     List<CandidateHost> any = getCandidateHosts(HostRequirement.any);
 
-    if (secondaries.isEmpty()) {
-      return any.iterator();
-    }
-
-    if (any.isEmpty()) {
-      return secondaries.iterator();
-    }
-
-    if (secondaries.get(secondaries.size() - 1).equals(any.get(0))) {
-      // When the last secondary's hostspec is the same as the first in "any" list, there's no need
-      // to attempt to connect it as "secondary"
+    if (  !preferred.isEmpty() && !any.isEmpty()
+        && preferred.get(preferred.size() - 1).hostSpec.equals(any.get(0).hostSpec)) {
+      // When the last preferred host's hostspec is the same as the first in "any" list, there's no need
+      // to attempt to connect it as "preferred"
       // Note: this is only an optimization
-      secondaries = rtrim(1, secondaries);
+      preferred = rtrim(1, preferred);
     }
-    return append(secondaries, any).iterator();
+    return append(preferred, any).iterator();
   }
 
   private List<CandidateHost> getCandidateHosts(HostRequirement hostRequirement) {


=====================================
src/main/java/org/postgresql/jdbc/PgResultSet.java
=====================================
@@ -74,6 +74,7 @@ import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.OffsetDateTime;
 import java.time.OffsetTime;
+import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -671,8 +672,19 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS
       }
     } else {
       // string
-      if (oid == Oid.TIMESTAMPTZ || oid == Oid.TIMESTAMP || oid == Oid.TIMETZ) {
-        return getTimestampUtils().toOffsetDateTime(castNonNull(getString(i)), oid != Oid.TIMETZ);
+
+      if (oid == Oid.TIMESTAMPTZ || oid == Oid.TIMESTAMP )  {
+
+        OffsetDateTime offsetDateTime = getTimestampUtils().toOffsetDateTime(castNonNull(getString(i)));
+        if ( offsetDateTime != OffsetDateTime.MAX && offsetDateTime != OffsetDateTime.MIN ) {
+          return offsetDateTime.withOffsetSameInstant(ZoneOffset.UTC);
+        } else {
+          return offsetDateTime;
+        }
+
+      }
+      if ( oid == Oid.TIMETZ ) {
+        return getTimestampUtils().toOffsetDateTime(castNonNull(getString(i)));
       }
     }
 


=====================================
src/main/java/org/postgresql/jdbc/TimestampUtils.java
=====================================
@@ -516,17 +516,30 @@ public class TimestampUtils {
     }
   }
 
+  /**
+   * Returns the offset date time object matching the given bytes with Oid#TIMETZ.
+   * Not used internally anymore, function is here to retain compatibility with previous versions
+   *
+   * @param t the time value
+   * @return the matching offset date time
+   * @deprecated was used internally, and not used anymore
+   */
+  @Deprecated
+  public OffsetDateTime toOffsetDateTime(Time t) {
+    // hardcode utc because the backend does not provide us the timezone
+    // hardcode UNIX epoch, JDBC requires OffsetDateTime but doesn't describe what date should be used
+    return t.toLocalTime().atDate(LocalDate.of(1970, 1, 1)).atOffset(ZoneOffset.UTC);
+  }
+
   /**
    * Parse a string and return a OffsetDateTime representing its value.
    *
-   * @param s The ISO formated date string to parse.
-   * @param adaptToUTC if true the timezone is adapted to be UTC;
-   *     this must be done for timestamp and timestamptz as they have no zone on server side
+   * @param s The ISO formatted date string to parse.
    * @return null if s is null or a OffsetDateTime of the parsed string s.
    * @throws SQLException if there is a problem parsing s.
    */
   public /* @PolyNull */ OffsetDateTime toOffsetDateTime(
-      /* @PolyNull */ String s, boolean adaptToUTC) throws SQLException {
+      /* @PolyNull */ String s) throws SQLException {
     if (s == null) {
       return null;
     }
@@ -545,9 +558,6 @@ public class TimestampUtils {
     final ParsedTimestamp ts = parseBackendTimestamp(s);
     OffsetDateTime result =
         OffsetDateTime.of(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, ts.nanos, ts.offset);
-    if (adaptToUTC) {
-      result = result.withOffsetSameInstant(ZoneOffset.UTC);
-    }
     if (ts.era == GregorianCalendar.BC) {
       return result.with(ChronoField.ERA, IsoEra.BCE.getValue());
     } else {


=====================================
src/main/java/org/postgresql/util/DriverInfo.java
=====================================
@@ -16,13 +16,13 @@ public final class DriverInfo {
   // Driver name
   public static final String DRIVER_NAME = "PostgreSQL JDBC Driver";
   public static final String DRIVER_SHORT_NAME = "PgJDBC";
-  public static final String DRIVER_VERSION = "42.3.4";
+  public static final String DRIVER_VERSION = "42.3.5";
   public static final String DRIVER_FULL_NAME = DRIVER_NAME + " " + DRIVER_VERSION;
 
   // Driver version
   public static final int MAJOR_VERSION = 42;
   public static final int MINOR_VERSION = 3;
-  public static final int PATCH_VERSION = 4;
+  public static final int PATCH_VERSION = 5;
 
   // JDBC specification
   public static final String JDBC_VERSION = "4.2";


=====================================
src/main/resources/META-INF/MANIFEST.MF
=====================================
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Implementation-Title: PostgreSQL JDBC Driver
 Bundle-License: BSD-2-Clause
 Automatic-Module-Name: org.postgresql.jdbc
-Implementation-Version: 42.3.4
+Implementation-Version: 42.3.5
 Specification-Vendor: Oracle Corporation
 Specification-Title: JDBC
 Implementation-Vendor-Id: org.postgresql


=====================================
src/test/java/org/postgresql/test/hostchooser/MultiHostsConnectionTest.java
=====================================
@@ -14,6 +14,7 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 import static org.postgresql.hostchooser.HostRequirement.any;
+import static org.postgresql.hostchooser.HostRequirement.preferPrimary;
 import static org.postgresql.hostchooser.HostRequirement.preferSecondary;
 import static org.postgresql.hostchooser.HostRequirement.primary;
 import static org.postgresql.hostchooser.HostRequirement.secondary;
@@ -237,6 +238,27 @@ public class MultiHostsConnectionTest {
     assertGlobalState(secondary1, "Secondary"); // was unknown, so tried to connect in order
   }
 
+  @Test
+  public void testConnectToPrimaryFirst() throws SQLException {
+    getConnection(preferPrimary, true, fake1, primary1, secondary1);
+    assertRemote(primaryIp);
+    assertGlobalState(fake1, "ConnectFail");
+    assertGlobalState(primary1, "Primary");
+    assertGlobalState(secondary1, null);
+
+    getConnection(primary, false, fake1, secondary1, primary1);
+    assertRemote(primaryIp);
+    assertGlobalState(fake1, "ConnectFail");
+    assertGlobalState(primary1, "Primary");
+    assertGlobalState(secondary1, "Secondary"); // tried as it was unknown
+
+    getConnection(preferPrimary, true, fake1, secondary1, primary1);
+    assertRemote(primaryIp);
+    assertGlobalState(fake1, "ConnectFail");
+    assertGlobalState(primary1, "Primary");
+    assertGlobalState(secondary1, "Secondary");
+  }
+
   @Test
   public void testConnectToPrimaryWithReadonlyTransactionMode() throws SQLException {
     con = TestUtil.openPrivilegedDB();
@@ -322,6 +344,47 @@ public class MultiHostsConnectionTest {
     assertTrue("Never tried to connect to fake node", fake1FoundTried);
   }
 
+  @Test
+  public void testLoadBalancing_preferPrimary() throws SQLException {
+    Set<String> connectedHosts = new HashSet<String>();
+    Set<HostSpec> tryConnectedHosts = new HashSet<HostSpec>();
+    for (int i = 0; i < 20; ++i) {
+      getConnection(preferPrimary, true, true, fake1, secondary1, secondary2, primary1);
+      connectedHosts.add(getRemoteHostSpec());
+      tryConnectedHosts.addAll(hostStatusMap.keySet());
+      if (tryConnectedHosts.size() == 4) {
+        break;
+      }
+    }
+
+    assertRemote(primaryIp);
+    assertEquals("Connected to hosts other than primary", new HashSet<String>(asList(primaryIp)),
+        connectedHosts);
+    assertEquals("Never tried to connect to fake node", 4, tryConnectedHosts.size());
+
+    getConnection(preferPrimary, false, true, fake1, secondary1, primary1);
+    assertRemote(primaryIp);
+
+    // connect to secondaries when there's no primary - with load balancing
+    connectedHosts.clear();
+    for (int i = 0; i < 20; ++i) {
+      getConnection(preferPrimary, false, true, fake1, secondary1, secondary2);
+      connectedHosts.add(getRemoteHostSpec());
+      if (connectedHosts.size() == 2) {
+        break;
+      }
+    }
+    assertEquals("Never connected to all secondary hosts", new HashSet<String>(asList(secondaryIP, secondaryIP2)),
+        connectedHosts);
+
+    // connect to secondary when there's no primary
+    getConnection(preferPrimary, true, true, fake1, secondary1);
+    assertRemote(secondaryIP);
+
+    getConnection(preferPrimary, false, true, fake1, secondary1);
+    assertRemote(secondaryIP);
+  }
+
   @Test
   public void testLoadBalancing_preferSecondary() throws SQLException {
     Set<String> connectedHosts = new HashSet<String>();


=====================================
src/test/java/org/postgresql/test/jdbc42/TimestampUtilsTest.java
=====================================
@@ -27,54 +27,66 @@ public class TimestampUtilsTest {
 
   @Test
   public void testToStringOfLocalTime() {
-    assertToStringOfLocalTime("00:00:00", "00:00:00");
-    assertToStringOfLocalTime("00:00:00.1", "00:00:00.1");
-    assertToStringOfLocalTime("00:00:00.12", "00:00:00.12");
-    assertToStringOfLocalTime("00:00:00.123", "00:00:00.123");
-    assertToStringOfLocalTime("00:00:00.1234", "00:00:00.1234");
-    assertToStringOfLocalTime("00:00:00.12345", "00:00:00.12345");
-    assertToStringOfLocalTime("00:00:00.123456", "00:00:00.123456");
-
-    assertToStringOfLocalTime("00:00:00.999999", "00:00:00.999999");
-    assertToStringOfLocalTime("00:00:00.999999", "00:00:00.999999499"); // 499 NanoSeconds
-    assertToStringOfLocalTime("00:00:01", "00:00:00.999999500"); // 500 NanoSeconds
-
-    assertToStringOfLocalTime("23:59:59", "23:59:59");
-
-    assertToStringOfLocalTime("23:59:59.999999", "23:59:59.999999");
-    assertToStringOfLocalTime("23:59:59.999999", "23:59:59.999999499"); // 499 NanoSeconds
-    assertToStringOfLocalTime("24:00:00", "23:59:59.999999500"); // 500 NanoSeconds
-    assertToStringOfLocalTime("24:00:00", "23:59:59.999999999"); // 999 NanoSeconds
+    assertToStringOfLocalTime("00:00:00");
+    assertToStringOfLocalTime("00:00:00.1");
+    assertToStringOfLocalTime("00:00:00.12");
+    assertToStringOfLocalTime("00:00:00.123");
+    assertToStringOfLocalTime("00:00:00.1234");
+    assertToStringOfLocalTime("00:00:00.12345");
+    assertToStringOfLocalTime("00:00:00.123456");
+
+    assertToStringOfLocalTime("00:00:00.999999");
+    assertToStringOfLocalTime("00:00:00.999999", "00:00:00.999999499", "499 NanoSeconds round down");
+    assertToStringOfLocalTime("00:00:01", "00:00:00.999999500", "500 NanoSeconds round up");
+
+    assertToStringOfLocalTime("23:59:59");
+
+    assertToStringOfLocalTime("23:59:59.999999");
+    assertToStringOfLocalTime("23:59:59.999999", "23:59:59.999999499", "499 NanoSeconds round down");
+    assertToStringOfLocalTime("24:00:00", "23:59:59.999999500", "500 NanoSeconds round up");
+    assertToStringOfLocalTime("24:00:00", "23:59:59.999999999", "999 NanoSeconds round up");
   }
 
-  private void assertToStringOfLocalTime(String expectedOutput, String inputTime) {
-    assertEquals("timestampUtils.toString(LocalTime.parse(" + inputTime + "))",
+  private void assertToStringOfLocalTime(String inputTime) {
+    assertToStringOfLocalTime(inputTime, inputTime, null);
+  }
+
+  private void assertToStringOfLocalTime(String expectedOutput, String inputTime, String message) {
+    assertEquals(
+        "timestampUtils.toString(LocalTime.parse(" + inputTime + "))"
+            + (message == null ? ": " + message : ""),
         expectedOutput,
         timestampUtils.toString(LocalTime.parse(inputTime)));
   }
 
   @Test
   public void testToLocalTime() throws SQLException {
-    assertToLocalTime("00:00:00", "00:00:00");
-
-    assertToLocalTime("00:00:00.1", "00:00:00.1");
-    assertToLocalTime("00:00:00.12", "00:00:00.12");
-    assertToLocalTime("00:00:00.123", "00:00:00.123");
-    assertToLocalTime("00:00:00.1234", "00:00:00.1234");
-    assertToLocalTime("00:00:00.12345", "00:00:00.12345");
-    assertToLocalTime("00:00:00.123456", "00:00:00.123456");
-    assertToLocalTime("00:00:00.999999", "00:00:00.999999");
-
-    assertToLocalTime("23:59:59", "23:59:59");
-    assertToLocalTime("23:59:59.999999", "23:59:59.999999"); // 0 NanoSeconds
-    assertToLocalTime("23:59:59.9999999", "23:59:59.9999999"); // 900 NanoSeconds
-    assertToLocalTime("23:59:59.99999999", "23:59:59.99999999"); // 990 NanoSeconds
-    assertToLocalTime("23:59:59.999999998", "23:59:59.999999998"); // 998 NanoSeconds
-    assertToLocalTime(LocalTime.MAX.toString(), "24:00:00");
+    assertToLocalTime("00:00:00");
+
+    assertToLocalTime("00:00:00.1");
+    assertToLocalTime("00:00:00.12");
+    assertToLocalTime("00:00:00.123");
+    assertToLocalTime("00:00:00.1234");
+    assertToLocalTime("00:00:00.12345");
+    assertToLocalTime("00:00:00.123456");
+    assertToLocalTime("00:00:00.999999");
+
+    assertToLocalTime("23:59:59");
+    assertToLocalTime("23:59:59.999999"); // 0 NanoSeconds
+    assertToLocalTime("23:59:59.9999999"); // 900 NanoSeconds
+    assertToLocalTime("23:59:59.99999999"); // 990 NanoSeconds
+    assertToLocalTime("23:59:59.999999998"); // 998 NanoSeconds
+    assertToLocalTime(LocalTime.MAX.toString(), "24:00:00", "LocalTime can't represent 24:00:00");
+  }
+
+  private void assertToLocalTime(String inputTime) throws SQLException {
+    assertToLocalTime(inputTime, inputTime, null);
   }
 
-  private void assertToLocalTime(String expectedOutput, String inputTime) throws SQLException {
-    assertEquals("timestampUtils.toLocalTime(" + inputTime + ")",
+  private void assertToLocalTime(String expectedOutput, String inputTime, String message) throws SQLException {
+    assertEquals(
+        "timestampUtils.toLocalTime(" + inputTime + ")"
+            + (message == null ? ": " + message : ""),
         LocalTime.parse(expectedOutput),
         timestampUtils.toLocalTime(inputTime));
   }



View it on GitLab: https://salsa.debian.org/java-team/libpostgresql-jdbc-java/-/commit/4e9f0e47c909f375fe661250281f534e0915b685

-- 
View it on GitLab: https://salsa.debian.org/java-team/libpostgresql-jdbc-java/-/commit/4e9f0e47c909f375fe661250281f534e0915b685
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20220506/0f239383/attachment.htm>


More information about the pkg-java-commits mailing list