Changeset: fade6c6960cc for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/fade6c6960cc
Added Files:
        src/main/java/org/monetdb/mcl/net/HandshakeOption.java
Removed Files:
        src/main/java/org/monetdb/mcl/net/HandshakeOptions.java
Modified Files:
        src/main/java/org/monetdb/jdbc/MonetConnection.java
        src/main/java/org/monetdb/mcl/net/MapiSocket.java
Branch: default
Log Message:

Refactor Handshake options

It was not clear and there were obscure bugs.


diffs (truncated from 430 to 300 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetConnection.java 
b/src/main/java/org/monetdb/jdbc/MonetConnection.java
--- a/src/main/java/org/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/org/monetdb/jdbc/MonetConnection.java
@@ -36,8 +36,7 @@ import java.util.concurrent.Executor;
 import org.monetdb.mcl.io.BufferedMCLReader;
 import org.monetdb.mcl.io.BufferedMCLWriter;
 import org.monetdb.mcl.io.LineType;
-import org.monetdb.mcl.net.HandshakeOptions;
-import org.monetdb.mcl.net.HandshakeOptions.Setting;
+import org.monetdb.mcl.net.HandshakeOption;
 import org.monetdb.mcl.net.MapiSocket;
 import org.monetdb.mcl.parser.HeaderLineParser;
 import org.monetdb.mcl.parser.MCLParseException;
@@ -166,7 +165,12 @@ public class MonetConnection
        MonetConnection(final Properties props)
                throws SQLException, IllegalArgumentException
        {
-       // for debug: System.out.println("New connection object. Received 
properties are: " + props.toString());
+               HandshakeOption.AutoCommit autoCommitSetting = new 
HandshakeOption.AutoCommit(true);
+               HandshakeOption.ReplySize replySizeSetting = new 
HandshakeOption.ReplySize(DEF_FETCHSIZE);
+               HandshakeOption.SizeHeader sizeHeaderSetting = new 
HandshakeOption.SizeHeader(true);
+               HandshakeOption.TimeZone timeZoneSetting = new 
HandshakeOption.TimeZone(0);
+
+               // for debug: System.out.println("New connection object. 
Received properties are: " + props.toString());
                // get supported property values from the props argument.
                // When a value is found add it to the internal conn_props list 
for use by getClientInfo().
                this.hostname = props.getProperty("host");
@@ -211,10 +215,10 @@ public class MonetConnection
                        conn_props.setProperty("hash", hash);
 
                String autocommit_prop = props.getProperty("autocommit");
-               boolean initial_autocommit = true;
                if (autocommit_prop != null) {
-                       initial_autocommit = 
Boolean.parseBoolean(autocommit_prop);
-                       conn_props.setProperty("autocommit", 
Boolean.toString(initial_autocommit));
+                       boolean ac = Boolean.parseBoolean(autocommit_prop);
+                       autoCommitSetting.set(ac);
+                       conn_props.setProperty("autocommit", 
Boolean.toString(ac));
                }
 
                final String fetchsize_prop = props.getProperty("fetchsize");
@@ -222,7 +226,7 @@ public class MonetConnection
                        try {
                                int fetchsize = 
Integer.parseInt(fetchsize_prop);
                                if (fetchsize > 0 || fetchsize == -1) {
-                                       this.defaultFetchSize = fetchsize;
+                                       replySizeSetting.set(fetchsize);
                                        conn_props.setProperty("fetchsize", 
fetchsize_prop);
                                } else {
                                        addWarning("Fetch size must either be 
positive or -1. Value " + fetchsize + " ignored", "M1M05");
@@ -291,16 +295,18 @@ public class MonetConnection
                        server.setDatabase(database);
                server.setLanguage(language);
 
+               // calculate our time zone offset
                final Calendar cal = Calendar.getInstance();
                int offsetMillis = cal.get(Calendar.ZONE_OFFSET) + 
cal.get(Calendar.DST_OFFSET);
                int offsetSeconds = offsetMillis / 1000;
-               final HandshakeOptions handshakeOptions = new 
HandshakeOptions();
-               handshakeOptions.set(Setting.AutoCommit, initial_autocommit ? 1 
: 0);
-               handshakeOptions.set(Setting.TimeZone, offsetSeconds);
-               handshakeOptions.set(Setting.ReplySize, defaultFetchSize);
-//             handshakeOptions.set(Setting.SizeHeader, 1);
-               server.setHandshakeOptions(handshakeOptions);
-               autoCommit = initial_autocommit;
+               timeZoneSetting.set(offsetSeconds);
+
+               server.setHandshakeOptions(new HandshakeOption[] {
+                               autoCommitSetting,
+                               replySizeSetting,
+                               sizeHeaderSetting,
+                               timeZoneSetting,
+               });
 
                // we're debugging here... uhm, should be off in real life
                if (debug) {
@@ -381,50 +387,21 @@ public class MonetConnection
                        lang = LANG_UNKNOWN;
                }
 
-               // The reply size is checked before every query and adjusted if
-               // necessary. Update our current belief of what the server is 
set to.
-               if 
(handshakeOptions.wasSentInHandshake(HandshakeOptions.Setting.ReplySize)) {
-                       this.curReplySize = 
handshakeOptions.get(HandshakeOptions.Setting.ReplySize);
+               // Now take care of any handshake options not handled during 
the handshake
+               if (replySizeSetting.isSent()) {
+                       this.curReplySize = replySizeSetting.get();
                }
-
-               for (Setting setting : new Setting[] { Setting.SizeHeader }) {
-                       if (handshakeOptions.mustSend(setting)) {
-                               Integer value = handshakeOptions.get(setting); 
// guaranteed by mustSend to be non-null
-                               String command = String.format("%s %d", 
setting.getXCommand(), value);
-                               sendControlCommand(command);
-                       }
-               }
-
-               // the following initialisers are only valid when the language 
is SQL...
+               this.defaultFetchSize = replySizeSetting.get();
                if (lang == LANG_SQL) {
-                       if (handshakeOptions.mustSend(Setting.AutoCommit)) {
-                               
setAutoCommit(handshakeOptions.get(Setting.AutoCommit) != 0);
+                       if (autoCommitSetting.mustSend(autoCommit)) {
+                               setAutoCommit(autoCommitSetting.get());
                        }
-
-                       // set our time zone on the server, if we haven't 
already
-                       if (handshakeOptions.mustSend(Setting.TimeZone)) {
-                               final StringBuilder tz = new StringBuilder(64);
-                               tz.append("SET TIME ZONE INTERVAL '");
-                               int offsetMinutes = 
handshakeOptions.get(Setting.TimeZone) / 60;
-                               if (offsetMinutes < 0) {
-                                       tz.append('-');
-                                       offsetMinutes = -offsetMinutes; // make 
it positive
-                               } else {
-                                       tz.append('+');
-                               }
-                               int offsetHours = offsetMinutes / 60;
-                               if (offsetHours < 10)
-                                       tz.append('0');
-                               tz.append(offsetHours).append(':');
-                               offsetMinutes -= offsetHours * 60;
-                               if (offsetMinutes < 10)
-                                       tz.append('0');
-                               tz.append(offsetMinutes).append("' HOUR TO 
MINUTE");
-                               sendIndependentCommand(tz.toString());
+                       if (sizeHeaderSetting.mustSend(false)) {
+                               sendControlCommand("sizeheader 1");
                        }
-
-                       // set sizeheader to 1 to enable sending "typesizes" 
info by the server (see mapi_set_size_header() in mapi.c)
-                       sendControlCommand("sizeheader 1");
+                       if (timeZoneSetting.mustSend(0)) {
+                               setTimezone(timeZoneSetting.get());
+                       }
                }
 
                // we're absolutely not closed, since we're brand new
@@ -1739,6 +1716,27 @@ public class MonetConnection
                return downloadHandler;
        }
 
+       public void setTimezone(int offsetSeconds) throws SQLException {
+               final StringBuilder tz = new StringBuilder(64);
+               tz.append("SET TIME ZONE INTERVAL '");
+               int offsetMinutes = offsetSeconds / 60;
+               if (offsetMinutes < 0) {
+                       tz.append('-');
+                       offsetMinutes = -offsetMinutes; // make it positive
+               } else {
+                       tz.append('+');
+               }
+               int offsetHours = offsetMinutes / 60;
+               if (offsetHours < 10)
+                       tz.append('0');
+               tz.append(offsetHours).append(':');
+               offsetMinutes -= offsetHours * 60;
+               if (offsetMinutes < 10)
+                       tz.append('0');
+               tz.append(offsetMinutes).append("' HOUR TO MINUTE");
+               sendIndependentCommand(tz.toString());
+       }
+
        /**
         * Local helper method to test whether the Connection object is closed
         * When closed it throws an SQLException
diff --git a/src/main/java/org/monetdb/mcl/net/HandshakeOption.java 
b/src/main/java/org/monetdb/mcl/net/HandshakeOption.java
new file mode 100644
--- /dev/null
+++ b/src/main/java/org/monetdb/mcl/net/HandshakeOption.java
@@ -0,0 +1,100 @@
+package org.monetdb.mcl.net;
+
+public abstract class HandshakeOption<T> {
+       protected final int level;
+       protected final String handshakeField;
+       boolean sent = false;
+       T desiredValue;
+
+       protected HandshakeOption(int level, String handshakeField, T 
desiredValue) {
+               if (desiredValue == null) {
+                       throw new IllegalArgumentException("initial value must 
not be null");
+               }
+               this.level = level;
+               this.handshakeField = handshakeField;
+               this.desiredValue = desiredValue;
+       }
+
+       public void set(T newValue) {
+               if (newValue == null) {
+                       throw new IllegalArgumentException("new value must not 
be null");
+               }
+               desiredValue = newValue;
+       }
+
+       public T get() {
+               return desiredValue;
+       }
+
+       public int getLevel() {
+               return level;
+       }
+
+       public String getFieldName() {
+               return handshakeField;
+       }
+
+       public boolean isSent() {
+               return sent;
+       }
+
+       public void setSent(boolean b) {
+               sent = b;
+       }
+
+       public boolean mustSend(T currentValue) {
+               if (sent)
+                       return false;
+               if (currentValue.equals(desiredValue))
+                       return false;
+               return true;
+       }
+
+       abstract long numericValue();
+
+       protected static class BooleanOption extends HandshakeOption<Boolean> {
+               protected BooleanOption(int level, String name, Boolean 
initialValue) {
+                       super(level, name, initialValue);
+               }
+
+               @Override
+               long numericValue() {
+                       return desiredValue ? 1 : 0;
+               }
+       }
+
+       public static class AutoCommit extends BooleanOption {
+               public AutoCommit(boolean autoCommit) {
+                       super(1, "auto_commit",  autoCommit);
+               }
+       }
+
+       public static class ReplySize extends HandshakeOption<Integer> {
+               public ReplySize(int size) {
+                       super(2, "reply_size", size);
+               }
+
+               @Override
+               long numericValue() {
+                       return desiredValue;
+               }
+       }
+
+       public static class SizeHeader extends BooleanOption {
+               public SizeHeader(boolean sendHeader) {
+                       super(3, "size_header", sendHeader);
+                       set(sendHeader);
+               }
+       }
+
+       public static class TimeZone extends HandshakeOption<Integer> {
+               public TimeZone(int offset) {
+                       super(5, "time_zone", offset);
+               }
+
+               @Override
+               long numericValue() {
+                       return desiredValue;
+               }
+       }
+}
diff --git a/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java 
b/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java
deleted file mode 100644
--- a/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0.  If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
- */
-
-package org.monetdb.mcl.net;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/** Keep track of MAPI handshake options.
- *
- * Recent server versions (from 2021) allow you to send configuration 
information during
- * the authentication handshake so no additional round trips are necessary
- * when that has completed.
- *
- * This class keeps track of the values themselves, and also of whether or not 
they should still be sent.
- */
-final public class HandshakeOptions {
-       HashMap<Setting,Integer> options = new HashMap<>();
-       int handshakeLevel = 0;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to