Changeset: 8368cbc670bf for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java?cmd=changeset;node=8368cbc670bf
Added 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:

Send reply size and time zone during initial handshake


diffs (233 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
@@ -35,6 +35,7 @@ import java.util.concurrent.Executor;
 
 import org.monetdb.mcl.io.BufferedMCLReader;
 import org.monetdb.mcl.io.BufferedMCLWriter;
+import org.monetdb.mcl.net.HandshakeOptions;
 import org.monetdb.mcl.net.MapiSocket;
 import org.monetdb.mcl.parser.HeaderLineParser;
 import org.monetdb.mcl.parser.MCLParseException;
@@ -257,6 +258,14 @@ public class MonetConnection
                        server.setDatabase(database);
                server.setLanguage(language);
 
+               HandshakeOptions handshakeOptions = new HandshakeOptions();
+               final Calendar cal = Calendar.getInstance();
+               int offsetMillis = cal.get(Calendar.ZONE_OFFSET) + 
cal.get(Calendar.DST_OFFSET);
+               int offsetSeconds = offsetMillis / 1000;
+               handshakeOptions.setTimeZone(offsetSeconds);
+               handshakeOptions.setReplySize(DEF_FETCHSIZE);
+               server.setHandshakeOptions(handshakeOptions);
+
                // we're debugging here... uhm, should be off in real life
                if (debug) {
                        try {
@@ -336,20 +345,27 @@ public class MonetConnection
                        lang = LANG_UNKNOWN;
                }
 
+               if (!handshakeOptions.mustSendReplySize()) {
+                       // Initially, it had to be sent. If it no more needs to 
be sent now,
+                       // it must have been sent during the auth 
challenge/response.
+                       // Record the value it was set to.
+                       this.curReplySize = handshakeOptions.getReplySize();
+               }
+
                // the following initialisers are only valid when the language 
is SQL...
                if (lang == LANG_SQL) {
                        // enable auto commit
                        setAutoCommit(true);
 
-                       // set our time zone on the server
-                       final Calendar cal = Calendar.getInstance();
-                       int offset = cal.get(Calendar.ZONE_OFFSET) + 
cal.get(Calendar.DST_OFFSET);
-                       offset /= (60 * 1000); // milliseconds to minutes
-                       String tz = offset < 0 ? "-" : "+";
-                       tz += (Math.abs(offset) / 60 < 10 ? "0" : "") + 
(Math.abs(offset) / 60) + ":";
-                       offset -= (offset / 60) * 60;
-                       tz += (offset < 10 ? "0" : "") + offset;
-                       sendIndependentCommand("SET TIME ZONE INTERVAL '" + tz 
+ "' HOUR TO MINUTE");
+                       // set our time zone on the server, if we haven't 
already
+                       if (handshakeOptions.mustSendTimeZone()) {
+                               int offsetMinutes = 
handshakeOptions.getTimeZone() / 60;
+                               String tz = offsetMinutes < 0 ? "-" : "+";
+                               tz += (Math.abs(offsetMinutes) / 60 < 10 ? "0" 
: "") + (Math.abs(offsetMinutes) / 60) + ":";
+                               offsetMinutes -= (offsetMinutes / 60) * 60;
+                               tz += (offsetMinutes < 10 ? "0" : "") + 
offsetMinutes;
+                               sendIndependentCommand("SET TIME ZONE INTERVAL 
'" + tz + "' HOUR TO MINUTE");
+                       }
                }
 
                // we're absolutely not closed, since we're brand new
diff --git a/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java 
b/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java
new file mode 100644
--- /dev/null
+++ b/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java
@@ -0,0 +1,98 @@
+package org.monetdb.mcl.net;
+
+/** Keep track of MAPI handshake options.
+ *
+ * Recent server versions 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 options to send, and whether they have already
+ * been sent.
+ */
+public class HandshakeOptions {
+
+       // public Boolean autoCommit;
+       int replySize;
+       // public Integer replySize;
+       // public Integer ColumnarProtocol;
+       int timeZone;
+
+       boolean mustSendReplySize;
+       boolean mustSendTimeZone;
+
+       public int getReplySize() {
+               return replySize;
+       }
+
+       public void setReplySize(int replySize) {
+               this.replySize = replySize;
+               this.mustSendReplySize = true;
+       }
+
+       public boolean mustSendReplySize() {
+               return mustSendReplySize;
+       }
+
+       public void mustSendReplySize(boolean mustSendReplySize) {
+               this.mustSendReplySize = mustSendReplySize;
+       }
+
+       public int getTimeZone() {
+               return timeZone;
+       }
+
+       public void setTimeZone(int timeZone) {
+               this.timeZone = timeZone;
+               this.mustSendTimeZone = true;
+       }
+
+       public boolean mustSendTimeZone() {
+               return mustSendTimeZone;
+       }
+
+       public void mustSendTimeZone(boolean mustSendTimeZone) {
+               this.mustSendTimeZone = mustSendTimeZone;
+       }
+
+       public String formatResponse(int serverLevel) {
+               StringBuilder opts = new StringBuilder(100);
+               if (mustSendReplySize()) {
+                       formatOption(opts, Level.ReplySize, serverLevel, 
replySize);
+                       mustSendReplySize(false);
+               }
+               if (mustSendTimeZone()) {
+                       formatOption(opts, Level.TimeZone, serverLevel, 
timeZone);
+                       mustSendTimeZone(false);
+               }
+
+               return opts.toString();
+       }
+
+       private void formatOption(StringBuilder opts, Level level, int 
serverLevel, int value) {
+               if (!level.isSupported(serverLevel))
+                       return;
+               if (opts.length() > 0) {
+                       opts.append(",");
+               }
+               opts.append(level.field);
+               opts.append("=");
+               opts.append(value);
+       }
+
+       public enum Level {
+               ReplySize("reply_size", 2),
+               TimeZone("time_zone", 5);
+
+               private final int level;
+               private final String field;
+
+               Level(String field, int level) {
+                       this.field = field;
+                       this.level = level;
+               }
+
+               public boolean isSupported(int serverLevel) {
+                       return this.level < serverLevel;
+               }
+       }
+}
diff --git a/src/main/java/org/monetdb/mcl/net/MapiSocket.java 
b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
--- a/src/main/java/org/monetdb/mcl/net/MapiSocket.java
+++ b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
@@ -122,6 +122,9 @@ public class MapiSocket {   /* cannot (yet
        /** A short in two bytes for holding the block size in bytes */
        private final byte[] blklen = new byte[2];
 
+       /** Options that can be sent during the auth handshake if the server 
supports it */
+       private HandshakeOptions handshakeOptions;
+
        /**
         * Constructs a new MapiSocket.
         */
@@ -533,11 +536,33 @@ public class MapiSocket { /* cannot (yet
                                }
 
                                // compose and return response
-                               return "BIG:"   // JVM byte-order is big-endian
-                                       + username + ":"
-                                       + pwhash + ":"
-                                       + language + ":"
-                                       + (database == null ? "" : database) + 
":";
+                               String response = "BIG:"    // JVM byte-order 
is big-endian
+                                               + username + ":"
+                                               + pwhash + ":"
+                                               + language + ":"
+                                               + (database == null ? "" : 
database) + ":";
+                               if (chaltok.length > 6) {
+                                       // this ':' delimits the FILETRANS 
field, currently empty because we don't support it.
+                                       response += ":";
+
+                                       // if supported, send handshake options
+                                       for (String part : 
chaltok[6].split(",")) {
+                                               if (part.startsWith("sql=") && 
handshakeOptions != null) {
+                                                       int level;
+                                                       try {
+                                                               level = 
Integer.parseInt(chaltok[6].substring(4));
+                                                       } catch 
(NumberFormatException e) {
+                                                               throw new 
MCLParseException("Invalid handshake level: " + chaltok[6]);
+                                                       }
+                                                       response += 
handshakeOptions.formatResponse(level);
+                                                       break;
+                                               }
+                                       }
+                                       // this ':' delimits the handshake 
options field.
+                                       response += ":";
+
+                               }
+                               return response;
                        default:
                                throw new MCLException("Unsupported protocol 
version: " + version);
                }
@@ -687,6 +712,14 @@ public class MapiSocket {  /* cannot (yet
                        log.flush();
        }
 
+       public void setHandshakeOptions(HandshakeOptions handshakeOptions) {
+               this.handshakeOptions = handshakeOptions;
+       }
+
+       public HandshakeOptions getHandshakeOptions() {
+               return handshakeOptions;
+       }
+
        /**
         * Inner class that is used to write data on a normal stream as a
         * blocked stream.  A call to the flush() method will write a
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to