Repository: pgjdbc/pgjdbc
Pull request #1713 (2020-02-21 23:53:31)

removemaster

davecramer: Replaces #1259 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1aead140..740262d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -112,6 +112,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 ### Changed
 - `ssl=true` implies `sslmode=verify-full`, that is it requires valid server certificate [cdeeaca4](https://github.com/pgjdbc/pgjdbc/commit/cdeeaca47dc3bc6f727c79a582c9e4123099526e)
 
+targetServerType=master has been deprecated in favour of targetServerType=primary. master
+will still be accepted but not documented.
 ### Added
 - Support for `sslmode=allow/prefer/require` [cdeeaca4](https://github.com/pgjdbc/pgjdbc/commit/cdeeaca47dc3bc6f727c79a582c9e4123099526e)
 
diff --git a/docs/documentation/head/connect.md b/docs/documentation/head/connect.md
index 5997ee77..98b31f8c 100644
--- a/docs/documentation/head/connect.md
+++ b/docs/documentation/head/connect.md
@@ -441,10 +441,12 @@ Connection conn = DriverManager.getConnection(url);
 * **targetServerType** = String
 
 	Allows opening connections to only servers with required state, 
-	the allowed values are any, master, slave, secondary, preferSlave and preferSecondary. 
-	The master/slave distinction is currently done by observing if the server allows writes. 
+	the allowed values are any, primary, master, slave, secondary, preferSlave and preferSecondary. 
+	The primary/secondary distinction is currently done by observing if the server allows writes. 
 	The value preferSecondary tries to connect to secondary if any are available, 
-	otherwise allows falls back to connecting also to master.
+	otherwise allows falls back to connecting also to primary.
+	- *N.B.* the words master and slave are being deprecated. We will silently accept them, but primary
+	and secondary are encouraged.
 
 * **hostRecheckSeconds** = int
 
@@ -549,14 +551,20 @@ postgres installation that has identical data on each node.
 For example streaming replication postgres or postgres-xc cluster.
 
 For example an application can create two connection pools. 
-One data source is for writes, another for reads. The write pool limits connections only to master node:
+One data source is for writes, another for reads. The write pool limits connections only to a primary node:
 
-`jdbc:postgresql://node1,node2,node3/accounting?targetServerType=master`.
+`jdbc:postgresql://node1,node2,node3/accounting?targetServerType=primary`.
 
-And read pool balances connections between slaves nodes, but allows connections also to master if no slaves are available:
+And read pool balances connections between secondary nodes, but allows connections also to a primary if no secondaries are available:
 
-`jdbc:postgresql://node1,node2,node3/accounting?targetServerType=preferSlave&loadBalanceHosts=true`
+`jdbc:postgresql://node1,node2,node3/accounting?targetServerType=preferSecondary&loadBalanceHosts=true`
 
+<<<<<<< HEAD
 If a slave fails, all slaves in the list will be tried first. If the case that there are no available slaves
 the master will be tried. If all of the servers are marked as "can't connect" in the cache then an attempt
 will be made to connect to all of the hosts in the URL in order.
+=======
+If a secondary fails, all secondaries in the list will be tried first. If the case that there are no available secondaries
+the primary will be tried. If all of the servers are marked as "can't connect" in the cache then an attempt
+will be made to connect to all of the hosts in the URL in order.
+>>>>>>> 263d23605b9e4900fc161da165829a6b2ae168fc
diff --git a/pgjdbc/src/main/java/org/postgresql/PGProperty.java b/pgjdbc/src/main/java/org/postgresql/PGProperty.java
index 2874f200..bac39d10 100644
--- a/pgjdbc/src/main/java/org/postgresql/PGProperty.java
+++ b/pgjdbc/src/main/java/org/postgresql/PGProperty.java
@@ -583,6 +583,7 @@ public enum PGProperty {
     null,
     "The password for the client's ssl key (ignored if sslpasswordcallback is set)"),
 
+
   /**
    * The classname instantiating {@code javax.security.auth.callback.CallbackHandler} to use.
    */
@@ -626,7 +627,7 @@ public enum PGProperty {
     "any",
     "Specifies what kind of server to connect",
     false,
-    new String[] {"any", "master", "slave", "secondary",  "preferSlave", "preferSecondary"}),
+    new String [] {"any", "primary", "master", "slave", "secondary",  "preferSlave", "preferSecondary"}),
 
   /**
    * Enable or disable TCP keep-alive. The default is {@code false}.
diff --git a/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java b/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java
index aec04473..9737a82e 100644
--- a/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java
+++ b/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java
@@ -255,10 +255,10 @@ public class ConnectionFactoryImpl extends ConnectionFactory {
         QueryExecutor queryExecutor = new QueryExecutorImpl(newStream, user, database,
             cancelSignalTimeout, info);
 
-        // Check Master or Secondary
+        // Check Primary or Secondary
         HostStatus hostStatus = HostStatus.ConnectOK;
         if (candidateHost.targetServerType != HostRequirement.any) {
-          hostStatus = isMaster(queryExecutor) ? HostStatus.Master : HostStatus.Secondary;
+          hostStatus = isPrimary(queryExecutor) ? HostStatus.Primary : HostStatus.Secondary;
         }
         GlobalHostStatusTracker.reportHostStatus(hostSpec, hostStatus);
         knownStates.put(hostSpec, hostStatus);
@@ -753,7 +753,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory {
 
   }
 
-  private boolean isMaster(QueryExecutor queryExecutor) throws SQLException, IOException {
+  private boolean isPrimary(QueryExecutor queryExecutor) throws SQLException, IOException {
     Tuple results = SetupQueryRunner.run(queryExecutor, "show transaction_read_only", true);
     String value = queryExecutor.getEncoding().decode(results.get(0));
     return value.equalsIgnoreCase("off");
diff --git a/pgjdbc/src/main/java/org/postgresql/hostchooser/HostRequirement.java b/pgjdbc/src/main/java/org/postgresql/hostchooser/HostRequirement.java
index c5b25989..d2ddf887 100644
--- a/pgjdbc/src/main/java/org/postgresql/hostchooser/HostRequirement.java
+++ b/pgjdbc/src/main/java/org/postgresql/hostchooser/HostRequirement.java
@@ -14,9 +14,19 @@ public enum HostRequirement {
       return status != HostStatus.ConnectFail;
     }
   },
+  /**
+   * @deprecated we no longer use the terms master or slave in the driver, or the PostgreSQL
+   *        project.
+   */
+  @Deprecated
   master {
     public boolean allowConnectingTo(HostStatus status) {
-      return status == HostStatus.Master || status == HostStatus.ConnectOK;
+      return primary.allowConnectingTo(status);
+    }
+  },
+  primary {
+    public boolean allowConnectingTo(HostStatus status) {
+      return status == HostStatus.Primary || status == HostStatus.ConnectOK;
     }
   },
   secondary {
@@ -35,17 +45,20 @@ public enum HostRequirement {
   /**
    * <p>The postgreSQL project has decided not to use the term slave to refer to alternate servers.
    * secondary or standby is preferred. We have arbitrarily chosen secondary.
-   * As of Jan 2018 in order not to break existint code we are going to accept both slave or
+   * As of Jan 2018 in order not to break existing code we are going to accept both slave or
    * secondary for names of alternate servers.</p>
    *
    * <p>The current policy is to keep accepting this silently but not document slave, or slave preferSlave</p>
    *
+   * <p>As of Jul 2018 silently deprecate the use of the word master as well</p>
+   *
    * @param targetServerType the value of {@code targetServerType} connection property
    * @return HostRequirement
    */
 
   public static HostRequirement getTargetServerType(String targetServerType) {
-    String allowSlave = targetServerType.replace("lave", "econdary");
+
+    String allowSlave = targetServerType.replace("lave", "econdary").replace("master", "primary");
     return valueOf(allowSlave);
   }
 
diff --git a/pgjdbc/src/main/java/org/postgresql/hostchooser/HostStatus.java b/pgjdbc/src/main/java/org/postgresql/hostchooser/HostStatus.java
index cb72fdaa..d303e8d0 100644
--- a/pgjdbc/src/main/java/org/postgresql/hostchooser/HostStatus.java
+++ b/pgjdbc/src/main/java/org/postgresql/hostchooser/HostStatus.java
@@ -11,6 +11,6 @@ package org.postgresql.hostchooser;
 public enum HostStatus {
   ConnectFail,
   ConnectOK,
-  Master,
+  Primary,
   Secondary
 }


Test patch:
diff --git a/pgjdbc/src/test/java/org/postgresql/test/hostchooser/MultiHostsConnectionTest.java b/pgjdbc/src/test/java/org/postgresql/test/hostchooser/MultiHostsConnectionTest.java
index 8c202946..a727864b 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/hostchooser/MultiHostsConnectionTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/hostchooser/MultiHostsConnectionTest.java
@@ -14,13 +14,14 @@ 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.master;
 import static org.postgresql.hostchooser.HostRequirement.preferSecondary;
+import static org.postgresql.hostchooser.HostRequirement.primary;
 import static org.postgresql.hostchooser.HostRequirement.secondary;
-import static org.postgresql.hostchooser.HostStatus.Master;
+import static org.postgresql.hostchooser.HostStatus.Primary;
 import static org.postgresql.hostchooser.HostStatus.Secondary;
 import static org.postgresql.test.TestUtil.closeDB;
 
+import org.postgresql.PGProperty;
 import org.postgresql.hostchooser.GlobalHostStatusTracker;
 import org.postgresql.hostchooser.HostRequirement;
 import org.postgresql.test.TestUtil;
@@ -45,12 +46,12 @@ public class MultiHostsConnectionTest {
 
   private static final String user = TestUtil.getUser();
   private static final String password = TestUtil.getPassword();
-  private static final String master1 = TestUtil.getServer() + ":" + TestUtil.getPort();
+  private static final String primary1 = TestUtil.getServer() + ":" + TestUtil.getPort();
   private static final String secondary1 = getSecondaryServer1() + ":" + getSecondaryPort1();
   private static final String secondary2 = getSecondaryServer2() + ":" + getSecondaryPort2();
   private static final String fake1 = "127.127.217.217:1";
 
-  private String masterIp;
+  private String primaryIp;
   private String secondaryIP;
   private String secondaryIP2;
   private Connection con;
@@ -68,7 +69,7 @@ public class MultiHostsConnectionTest {
     hostStatusMap = (Map<HostSpec, Object>) field.get(null);
 
     con = TestUtil.openDB();
-    masterIp = getRemoteHostSpec();
+    primaryIp = getRemoteHostSpec();
     closeDB(con);
 
     con = openSecondaryDB();
@@ -101,8 +102,8 @@ public class MultiHostsConnectionTest {
   private static Properties userAndPassword() {
     Properties props = new Properties();
 
-    props.setProperty("user", TestUtil.getUser());
-    props.setProperty("password", TestUtil.getPassword());
+    PGProperty.USER.set(props,TestUtil.getUser());
+    PGProperty.PASSWORD.set(props,TestUtil.getPassword());
     return props;
   }
 
@@ -153,12 +154,12 @@ public class MultiHostsConnectionTest {
     }
 
     Properties props = new Properties();
-    props.setProperty("user", user);
-    props.setProperty("password", password);
-    props.setProperty("targetServerType", hostType.name());
-    props.setProperty("hostRecheckSeconds", "2");
+    PGProperty.USER.set(props,user);
+    PGProperty.PASSWORD.set(props,password);
+    PGProperty.TARGET_SERVER_TYPE.set(props,hostType.name());
+    PGProperty.HOST_RECHECK_SECONDS.set(props, 2);
     if (lb) {
-      props.setProperty("loadBalanceHosts", "true");
+      PGProperty.LOAD_BALANCE_HOSTS.set(props,"true");
     }
 
     StringBuilder sb = new StringBuilder();
@@ -205,70 +206,70 @@ public class MultiHostsConnectionTest {
 
   @Test
   public void testConnectToAny() throws SQLException {
-    getConnection(any, fake1, master1);
-    assertRemote(masterIp);
-    assertGlobalState(master1, "ConnectOK");
+    getConnection(any, fake1, primary1);
+    assertRemote(primaryIp);
+    assertGlobalState(primary1, "ConnectOK");
     assertGlobalState(fake1, "ConnectFail");
 
     getConnection(any, fake1, secondary1);
     assertRemote(secondaryIP);
     assertGlobalState(secondary1, "ConnectOK");
 
-    getConnection(any, fake1, master1);
-    assertRemote(masterIp);
-    assertGlobalState(master1, "ConnectOK");
+    getConnection(any, fake1, primary1);
+    assertRemote(primaryIp);
+    assertGlobalState(primary1, "ConnectOK");
     assertGlobalState(fake1, "ConnectFail");
   }
 
   @Test
   public void testConnectToMaster() throws SQLException {
-    getConnection(master, true, fake1, master1, secondary1);
-    assertRemote(masterIp);
+    getConnection(primary, true, fake1, primary1, secondary1);
+    assertRemote(primaryIp);
     assertGlobalState(fake1, "ConnectFail");
-    assertGlobalState(master1, "Master");
+    assertGlobalState(primary1, "Primary");
     assertGlobalState(secondary1, null);
 
-    getConnection(master, false, fake1, secondary1, master1);
-    assertRemote(masterIp);
+    getConnection(primary, false, fake1, secondary1, primary1);
+    assertRemote(primaryIp);
     assertGlobalState(fake1, "ConnectFail"); // cached
-    assertGlobalState(master1, "Master"); // connected to master
+    assertGlobalState(primary1, "Primary"); // connected to primary
     assertGlobalState(secondary1, "Secondary"); // was unknown, so tried to connect in order
   }
 
   @Test
   public void testConnectToSecondary() throws SQLException {
-    getConnection(secondary, true, fake1, secondary1, master1);
+    getConnection(secondary, true, fake1, secondary1, primary1);
     assertRemote(secondaryIP);
     assertGlobalState(fake1, "ConnectFail");
     assertGlobalState(secondary1, "Secondary");
-    assertGlobalState(master1, null);
+    assertGlobalState(primary1, null);
 
-    getConnection(secondary, false, fake1, master1, secondary1);
+    getConnection(secondary, false, fake1, primary1, secondary1);
     assertRemote(secondaryIP);
     assertGlobalState(fake1, "ConnectFail"); // cached
     assertGlobalState(secondary1, "Secondary"); // connected
-    assertGlobalState(master1, "Master"); // tried as it was unknown
+    assertGlobalState(primary1, "Primary"); // tried as it was unknown
   }
 
   @Test
   public void testConnectToSecondaryFirst() throws SQLException {
-    getConnection(preferSecondary, true, fake1, secondary1, master1);
+    getConnection(preferSecondary, true, fake1, secondary1, primary1);
     assertRemote(secondaryIP);
     assertGlobalState(fake1, "ConnectFail");
     assertGlobalState(secondary1, "Secondary");
-    assertGlobalState(master1, null);
+    assertGlobalState(primary1, null);
 
-    getConnection(secondary, false, fake1, master1, secondary1);
+    getConnection(secondary, false, fake1, primary1, secondary1);
     assertRemote(secondaryIP);
     assertGlobalState(fake1, "ConnectFail");
     assertGlobalState(secondary1, "Secondary");
-    assertGlobalState(master1, "Master"); // tried as it was unknown
+    assertGlobalState(primary1, "Primary"); // tried as it was unknown
 
-    getConnection(preferSecondary, true, fake1, master1, secondary1);
+    getConnection(preferSecondary, true, fake1, primary1, secondary1);
     assertRemote(secondaryIP);
     assertGlobalState(fake1, "ConnectFail");
     assertGlobalState(secondary1, "Secondary");
-    assertGlobalState(master1, "Master");
+    assertGlobalState(primary1, "Primary");
   }
 
   @Test
@@ -285,14 +286,14 @@ public class MultiHostsConnectionTest {
     Set<String> connectedHosts = new HashSet<String>();
     boolean fake1FoundTried = false;
     for (int i = 0; i < 20; ++i) {
-      getConnection(any, true, true, fake1, master1, secondary1);
+      getConnection(any, true, true, fake1, primary1, secondary1);
       connectedHosts.add(getRemoteHostSpec());
       fake1FoundTried |= hostStatusMap.containsKey(hostSpec(fake1));
       if (connectedHosts.size() == 2 && fake1FoundTried) {
         break;
       }
     }
-    assertEquals("Never connected to all hosts", new HashSet<String>(asList(masterIp, secondaryIP)),
+    assertEquals("Never connected to all hosts", new HashSet<String>(asList(primaryIp, secondaryIP)),
         connectedHosts);
     assertTrue("Never tried to connect to fake node", fake1FoundTried);
   }
@@ -302,7 +303,7 @@ public class MultiHostsConnectionTest {
     Set<String> connectedHosts = new HashSet<String>();
     Set<HostSpec> tryConnectedHosts = new HashSet<HostSpec>();
     for (int i = 0; i < 20; ++i) {
-      getConnection(preferSecondary, true, true, fake1, master1, secondary1, secondary2);
+      getConnection(preferSecondary, true, true, fake1, primary1, secondary1, secondary2);
       connectedHosts.add(getRemoteHostSpec());
       tryConnectedHosts.addAll(hostStatusMap.keySet());
       if (tryConnectedHosts.size() == 4) {
@@ -313,11 +314,11 @@ public class MultiHostsConnectionTest {
         connectedHosts);
     assertEquals("Never tried to connect to fake node",4, tryConnectedHosts.size());
 
-    getConnection(preferSecondary, false, true, fake1, master1, secondary1);
+    getConnection(preferSecondary, false, true, fake1, primary1, secondary1);
     assertRemote(secondaryIP);
     connectedHosts.clear();
     for (int i = 0; i < 20; ++i) {
-      getConnection(preferSecondary, false, true, fake1, master1, secondary1, secondary2);
+      getConnection(preferSecondary, false, true, fake1, primary1, secondary1, secondary2);
       connectedHosts.add(getRemoteHostSpec());
       if (connectedHosts.size() == 2) {
         break;
@@ -326,12 +327,12 @@ public class MultiHostsConnectionTest {
     assertEquals("Never connected to all secondary hosts", new HashSet<String>(asList(secondaryIP, secondaryIP2)),
         connectedHosts);
 
-    // connect to master when there's no secondary
-    getConnection(preferSecondary, true, true, fake1, master1);
-    assertRemote(masterIp);
+    // connect to primary when there's no secondary
+    getConnection(preferSecondary, true, true, fake1, primary1);
+    assertRemote(primaryIp);
 
-    getConnection(preferSecondary, false, true, fake1, master1);
-    assertRemote(masterIp);
+    getConnection(preferSecondary, false, true, fake1, primary1);
+    assertRemote(primaryIp);
   }
 
   @Test
@@ -339,7 +340,7 @@ public class MultiHostsConnectionTest {
     Set<String> connectedHosts = new HashSet<String>();
     Set<HostSpec> tryConnectedHosts = new HashSet<HostSpec>();
     for (int i = 0; i < 20; ++i) {
-      getConnection(secondary, true, true, fake1, master1, secondary1, secondary2);
+      getConnection(secondary, true, true, fake1, primary1, secondary1, secondary2);
       connectedHosts.add(getRemoteHostSpec());
       tryConnectedHosts.addAll(hostStatusMap.keySet());
       if (tryConnectedHosts.size() == 4) {
@@ -348,13 +349,13 @@ public class MultiHostsConnectionTest {
     }
     assertEquals("Did not attempt to connect to all salve hosts", new HashSet<String>(asList(secondaryIP, secondaryIP2)),
         connectedHosts);
-    assertEquals("Did not attempt to connect to master and fake node", 4, tryConnectedHosts.size());
+    assertEquals("Did not attempt to connect to primary and fake node", 4, tryConnectedHosts.size());
 
-    getConnection(preferSecondary, false, true, fake1, master1, secondary1);
+    getConnection(preferSecondary, false, true, fake1, primary1, secondary1);
     assertRemote(secondaryIP);
     connectedHosts.clear();
     for (int i = 0; i < 20; ++i) {
-      getConnection(secondary, false, true, fake1, master1, secondary1, secondary2);
+      getConnection(secondary, false, true, fake1, primary1, secondary1, secondary2);
       connectedHosts.add(getRemoteHostSpec());
       if (connectedHosts.size() == 2) {
         break;
@@ -366,33 +367,33 @@ public class MultiHostsConnectionTest {
 
   @Test
   public void testHostRechecks() throws SQLException, InterruptedException {
-    GlobalHostStatusTracker.reportHostStatus(hostSpec(master1), Secondary);
-    GlobalHostStatusTracker.reportHostStatus(hostSpec(secondary1), Master);
+    GlobalHostStatusTracker.reportHostStatus(hostSpec(primary1), Secondary);
+    GlobalHostStatusTracker.reportHostStatus(hostSpec(secondary1), Primary);
     GlobalHostStatusTracker.reportHostStatus(hostSpec(fake1), Secondary);
 
     try {
-      getConnection(master, false, fake1, secondary1, master1);
+      getConnection(primary, false, fake1, secondary1, primary1);
       fail();
     } catch (SQLException ex) {
     }
 
-    GlobalHostStatusTracker.reportHostStatus(hostSpec(master1), Secondary);
-    GlobalHostStatusTracker.reportHostStatus(hostSpec(secondary1), Master);
+    GlobalHostStatusTracker.reportHostStatus(hostSpec(primary1), Secondary);
+    GlobalHostStatusTracker.reportHostStatus(hostSpec(secondary1), Primary);
     GlobalHostStatusTracker.reportHostStatus(hostSpec(fake1), Secondary);
 
     SECONDS.sleep(3);
 
-    getConnection(master, false, secondary1, fake1, master1);
-    assertRemote(masterIp);
+    getConnection(primary, false, secondary1, fake1, primary1);
+    assertRemote(primaryIp);
   }
 
   @Test
   public void testNoGoodHostsRechecksEverything() throws SQLException, InterruptedException {
-    GlobalHostStatusTracker.reportHostStatus(hostSpec(master1), Secondary);
+    GlobalHostStatusTracker.reportHostStatus(hostSpec(primary1), Secondary);
     GlobalHostStatusTracker.reportHostStatus(hostSpec(secondary1), Secondary);
     GlobalHostStatusTracker.reportHostStatus(hostSpec(fake1), Secondary);
 
-    getConnection(master, false, secondary1, fake1, master1);
-    assertRemote(masterIp);
+    getConnection(primary, false, secondary1, fake1, primary1);
+    assertRemote(primaryIp);
   }
 }